我有一个由 SQL Server 数据库支持的 Web 应用程序。它有一份报告,结合了选定学期的学生和特定的方式。下图显示了选择学期和学生人数的界面。
用户选择学期并输入学生人数。为了清楚起见,假设用户输入3
学生并选择1th
学期2th
。系统应返回所有注册的学生1th
和2th
学期如下:
------------------------
Id StudentName Semester
------------------------
1 A First
4 D First
7 G First
2 B Second
3 C Second
5 E Second
9 I First
10 J First
12 L First
6 F Second
8 H Second
11 K Second
数据集如下:
学生桌
-----------------
Id StudentName
-----------------
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I
10 J
11 K
12 L
学期表
-----------------
Id Semester
-----------------
1 First
2 Second
3 Third
报名表
----------------------------
Id StudentID SemesterID
----------------------------
1 1 1
2 2 2
3 3 2
4 4 1
5 5 2
6 6 2
7 7 1
8 8 2
9 9 1
10 10 1
11 11 2
12 12 1
关于如何显示上述表格的记录的任何想法?
解决此问题的一种方法是从
Enrollment
表格开始。使用ROW_NUMBER
排名功能,您可以按以下组分配行号SemesterID
:对于您的示例,您将获得如下输出:
现在减去一个
RN
,然后将结果除以所需的学生人数。如果学生人数是3,那么你会发现前面的计算变成了一个序列进入
也就是说,你会得到一个由多组重复数字组成的序列,每组三个(因为我们除以三)。您可以将该结果用作主要排序标准。
选择
SemesterID
作为您的第二个标准和Id
或StudentID
作为第三个标准,所以现在查询将如下所示:这将是基于提供的样本的输出:
您可以看到行的顺序已经与预期的输出相匹配,您只需将
StudentID
and替换SemesterID
为它们的描述并去掉GroupID
. 将上述查询声明为派生表或 CTE,然后将表连接Student
到Semester
它。对于我的回答,我选择了 CTE 选项,这就是我得到的:输出:
如您所见,到目前为止,我们的查询非常适合提供的示例:结果现在与您的预期输出精确匹配。但是查询还没有完成:缺少学期的过滤器。
假设学期将以逗号分隔的名称/描述列表的形式提供,您可以做的是将该列表转换为行集,每行有一个名称/描述。然后,您可以将该行集与
Semester
表进行匹配,以仅包含选定的学期。出于此答案的目的,我假设您使用的是 SQL Server 2016 或更高版本,以便可以使用内置SPLIT_STRING
函数来帮助实现学期过滤器:在 SQL Server 的早期版本中,您必须提供自己的方法将字符串列表转换为子字符串的行集。值得庆幸的是,互联网上的解决方案比比皆是,包括这里和 Stack Overflow 上专门针对这个问题的许多问题和答案。Aaron Bertrand在他的博客文章中讨论了各种方法,以正确的方式拆分字符串 - 或次佳方式,这可能是一个很好的起点。
至于我们的查询,还有最后一步要做:参数化。在上述查询中,学生人数和所选学期列表都是硬编码的。最终解决方案将需要使用参数引用而不是硬编码值,如下所示:
此解决方案的现场演示可在db<>fiddle.uk 获得。
披露:这个答案部分借用了Josh Darnell现在删除的答案。