SQL-Server:继续最后一个值而不是 NULL,分区不正确

Posted

技术标签:

【中文标题】SQL-Server:继续最后一个值而不是 NULL,分区不正确【英文标题】:SQL-Server: Continue Last Value other then NULL, Incorrect Partition By 【发布时间】:2020-12-14 14:24:05 【问题描述】:

我想在Last_EmployeeId 列中为每个RoomNumber 显示最后一个EmployeeId。所以当有NULL 值时,我应该返回EmployeeId 而不是NULL。下面的查询几乎可以解决Partition by value_partition 的问题,因为value_partition 为非空记录显示了不同的数字。但是,在某个点上,value_partition 对 NULL 和非 NULL 记录显示完全相同的数字(大约 3000 条记录之后)。因此,它也会为所有不相关的房间返回 EmployeeId(正如您在下面粘贴的数据 sn-p 中看到的那样)。

我使用以下代码:

;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

如您所见,现在不仅RoomNumber 33,而且34 和401 继续显示607。 如何找到正确显示最后一个“EmployeeId”的方法?

有什么建议吗?

【问题讨论】:

【参考方案1】:

我了解您希望在每个房间的基础上使用最后一个非null employeeid。如果 SQL Server 支持选项 ignore nulls 到窗口函数 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

【讨论】:

以上是关于SQL-Server:继续最后一个值而不是 NULL,分区不正确的主要内容,如果未能解决你的问题,请参考以下文章

SQL-server'WEEKDAY'不是公认的内置函数名称[关闭]

股票预测:GRU 模型预测相同的给定值而不是未来的股票价格

SQL-Server:备份集包含一个数据库的备份,而不是现有的

在go语言中,如何在反引号中调用变量的值而不是变量名

SQL-Server:是不是有相当于一般存储过程执行的触发器

str.contains 是不是有替代代码用于一个值而不是系列?