#sql #sql-server #datetime #sql-server-2012 #gaps-and-islands
#sql #sql-server #дата и время #sql-server-2012 #пробелы и острова
Вопрос:
Я хочу показать последнее EmployeeId
значение в столбце Last_EmployeeId
для каждого RoomNumber
. Поэтому, когда есть NULL
значение, я должен вернуть EmployeeId
вместо NULL
. Приведенный ниже запрос почти делает трюк Partition by value_partition
, потому value_partition
что показывает другое число для ненулевых записей. Однако в определенный момент value_partition
отображается точно такое же число как для нулевых, так и для ненулевых записей (после ~ 3000 записей). Как следствие, он возвращает EmployeeId
также для всех несвязанных комнат (как вы можете видеть во вставленном фрагменте данных ниже).
Я использую следующий код:
;WITH Rooms_Rank AS (
SELECT
Rooms.*
,ROW_NUMBER() OVER (PARTITION BY Rooms.RoomNumber ORDER BY Rooms.[Date]) -
ROW_NUMBER() OVER (PARTITION BY Rooms.RoomNumber, Rooms.beginDate ORDER BY Rooms.[Date]) AS Rnk--[Services].beginDate ORDER BY RoomDate.[Date]) AS Rnk
FROM Rooms
)
SELECT
[Date]
,RoomNumber
,EmployeeId
,value_partition
,first_value(EmployeeId) OVER (PARTITION BY value_partition ORDER BY [Date]) AS Last_EmployeeId
FROM (
SELECT *,
SUM(CASE WHEN EmployeeId is null THEN 0 ELSE 1 END) OVER (ORDER BY RoomNumber, CAST([Date] AS DATE)) AS value_partition
FROM Rooms_Rank
) AS q
ORDER BY [Date] ASC, RoomNumber
Небольшая выборка набора данных (поскольку эта проблема возникает только после записей 3000 )
Дата | Номер комнаты | EmployeeID | value_partition | Last_EmployeeId |
---|---|---|---|---|
2020-10-12 | 33 | 607 | 133 | 607 |
2020-10-12 | 34 | NULL | 136 | NULL |
2020-10-12 | 401 | NULL | 136 | NULL |
2020-10-12 | 71 | NULL | 223 | NULL |
2020-10-13 | 33 | 607 | 134 | 607 |
2020-10-13 | 34 | NULL | 136 | NULL |
2020-10-13 | 401 | NULL | 136 | NULL |
2020-10-13 | 71 | NULL | 223 | NULL |
2020-10-14 | 33 | 607 | 135 | 607 |
2020-10-14 | 34 | NULL | 136 | NULL |
2020-10-14 | 401 | NULL | 136 | NULL |
2020-10-14 | 71 | NULL | 223 | NULL |
2020-10-15 | 33 | 607 | 136 | 607 |
2020-10-15 | 34 | NULL | 136 | 607 |
2020-10-15 | 401 | NULL | 136 | 607 |
2020-10-15 | 71 | NULL | 223 | NULL |
2020-10-16 | 33 | NULL | 136 | 607 |
2020-10-16 | 34 | NULL | 136 | 607 |
2020-10-16 | 401 | NULL | 136 | 607 |
2020-10-16 | 71 | NULL | 223 | NULL |
Как вы можете видеть, 607 продолжает отображаться не только RoomNumber
для 33, но также для 34 и 401. Как я могу найти способ правильно отобразить последний ‘EmployeeID’?
Есть предложения?
Ответ №1:
Я понимаю, что вам нужно последнее значение, отличное null
employeeid
от значения для каждой комнаты. Это было бы прямолинейно, если бы SQL Server поддерживал функцию option ignore nulls
to window lag()
— увы, очень немногие базы данных поддерживают, и SQL Server не является одним из них.
Вместо этого мы можем решить эту проблему как проблему пробелов и островов.Мы можем распределять записи по группам, используя совокупное количество ненулевых значений, а затем выбрать единственное ненулевое значение для каждой группы:
select t.*,
max(employeeid) over(partition by roomnumber, grp order by date) as lastemployeeid
from (
select rr.*,
count(employeeid) over(partition by roomnumber order by date) grp
from rooms_rank rr
) rr