With Numbers As
(
Select Row_Number() Over ( Order By C1.object_id ) As Value
From sys.syscolumns As C1
Cross Join sys.syscolumns As C2
)
, NumberedStudents As
(
Select people_id, people_name, dorm_building, dorm_room
, Row_Number() Over ( Partition By dorm_building, dorm_room Order By people_id ) As OccupantNum
From Students
)
Select ...
From DormRooms
Join Numbers
On N.Value <= DormRooms.max_occupancy
Left Join NumberedStudents
On NumberedStudents.dorm_building = DormRooms.dorm_building
And NumberedStudents.dorm_room = DormRooms.dorm_room
And NumberedStudents.OccupantNum= Numbers
I'm using two features in this solution which are available in SQL Server 2005 and beyond. The first is common-table expression or CTE for short and the second is a ranking function (in this case Row_Number). The common-table expressions are the Numbers
table and the NumberedStudents
table. Think of these as saved views or queries. The Numbers
CTE creates a sequential list of numbers by cross joining any two tables (I chose sys.syscolumns). That enables me to generate the "placeholder" rows you requested. The Row_Number function simply creates a sequential list of numbers for every row returned.
In the NumberedStudents CTE, I am also using the Partition By
feature with the Row_Number function which restarts the numbering of occupants for each dorm_building and dorm_room. This will effectively give a sequential number to each student in the room.