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
Я использую в этом решении две функции, доступные в SQL Server 2005 и более поздних версиях. Первое - это выражение общей таблицы или CTE для краткости, а второе - функция ранжирования (в данном случае Row_Number). Выражениями общей таблицы являются таблица Numbers
и таблица NumberedStudents
. Думайте об этом как о сохраненных видах или запросах. Numbers
CTE создает последовательный список чисел путем перекрестного соединения любых двух таблиц (я выбрал sys.syscolumns). Это позволяет мне генерировать запрошенные вами строки-заполнители. Функция Row_Number просто создает последовательный список чисел для каждой возвращаемой строки.
В CTE NumberedStudents я также использую функцию Partition By
с функцией Row_Number, которая перезапускает нумерацию жителей для каждого dorm_building и dorm_room. Это даст эффективный номер каждому студенту в комнате.