SQL-服务器:继续除 NULL 之外的最后一个值,不正确的分区依据
SQL-Server: Continue Last Value other then NULL, Incorrect Partition By
我想为每个 RoomNumber
在 Last_EmployeeId
列中显示最后一个 EmployeeId
。所以当有 NULL
值时,我应该 return 而 EmployeeId
而不是 NULL
。下面的查询几乎达到了 Partition by value_partition
的目的,因为 value_partition
为非空记录显示了不同的数字。但是,在某个时刻 value_partition
显示 NULL 和非 NULL 记录的数字完全相同(在 ~3000 条记录之后)。因此,它 returns 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+之后)
Date
RoomNumber
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' 的方法?
有什么建议吗?
我了解到您想要每个房间的最后一个非null
employeeid
。如果 SQL 服务器支持选项 ignore nulls
到 window 函数 lag()
,那将是直截了当的 - 唉,很少有数据库这样做,而 SQL 服务器不是其中之一。
相反,我们可以解决这个问题,因为间隙和孤岛 problem.We 可以使用非空值的累积计数将记录分组,然后选择每组唯一的非空值:
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
我想为每个 RoomNumber
在 Last_EmployeeId
列中显示最后一个 EmployeeId
。所以当有 NULL
值时,我应该 return 而 EmployeeId
而不是 NULL
。下面的查询几乎达到了 Partition by value_partition
的目的,因为 value_partition
为非空记录显示了不同的数字。但是,在某个时刻 value_partition
显示 NULL 和非 NULL 记录的数字完全相同(在 ~3000 条记录之后)。因此,它 returns 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+之后)
Date | RoomNumber | 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' 的方法?
有什么建议吗?
我了解到您想要每个房间的最后一个非null
employeeid
。如果 SQL 服务器支持选项 ignore nulls
到 window 函数 lag()
,那将是直截了当的 - 唉,很少有数据库这样做,而 SQL 服务器不是其中之一。
相反,我们可以解决这个问题,因为间隙和孤岛 problem.We 可以使用非空值的累积计数将记录分组,然后选择每组唯一的非空值:
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