I have a web application backed by SQL Server database. It has a report, that combines students of selected semesters and a specific way. the following image show the interface for selecting semester and number of students.
The user selects the semesters and enters numbers of students.
To be clear, suppose a user enters 3
students and selects 1th
and 2th
semesters. The system should return all students which are enrolled in 1th
and 2th
semester as following:
------------------------
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
The dataset is as follow:
Student Table
-----------------
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
Semester Table
-----------------
Id Semester
-----------------
1 First
2 Second
3 Third
Enrollment Table
----------------------------
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
Any idea on how to show the records of the above table as mentioned?
Best Answer
One way to approach this is to start with the
Enrollment
table. Using theROW_NUMBER
ranking function, you can assign row numbers in groups ofSemesterID
:For your example you will get output like this:
Now subtract one from
RN
and then divide the result by the required number of students. If the number of students is 3, then you will find that the aforementioned calculation turns a sequence ofinto
That is to say, you will get a sequence consisting of groups of repeating numbers, three per group (because we divided by three). You can use that result as the primary sorting criterion.
Choose
SemesterID
as your second criterion andId
orStudentID
as the third, so now the query will look like this:And this will be its output based on the sample provided:
You can see that the order of rows already matches the expected output, you just need to replace
StudentID
andSemesterID
with their descriptions and get rid of theGroupID
. Declare the above query as either a derived table or a CTE and then join tablesStudent
andSemester
to it. For my answer I chose the CTE option, and this is what I got:Output:
As you can see, the query we have so far works perfectly for the provided example: the results now match your expected output precisely. But the query is not finished yet: the filter on semester is missing.
Assuming that semesters will be provided as a comma-separated list of names/descriptions, what you can do is turn that list into a row set, with one name/description per row. You can then match that row set against the
Semester
table to include just the selected semesters. For the purpose of this answer I am assuming that you are using SQL Server 2016 or later version, so that the built-inSPLIT_STRING
function can be used to help implement the semester filter:In an earlier version of SQL Server you will have to provide your own method of turning a string list into a row set of substrings. Thankfully, solutions abound on the Internet, including the many questions and answers dedicated to this problem both here and on Stack Overflow. Aaron Bertrand discusses various methods in his blog article, Split strings the right way – or the next best way, which can be a good starting point.
As for our query, there remains one last step to take: parametrisation. Both the number of students and the list of selected semesters were hard-coded in the above queries. The final solution will need to use parameter references instead of the hard-coded values, something like this:
A live demo of this solution is available at db<>fiddle.uk.
Disclosure: this answer borrows partly from the now deleted answer by Josh Darnell.