SQL-服务器:继续除 NULL 之外的最后一个值,不正确的分区依据

SQL-Server: Continue Last Value other then NULL, Incorrect Partition By

我想为每个 RoomNumberLast_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