首页 > 解决方案 > 随着时间的推移选择每个不同的值,而不会丢失两者之间的 NULL

问题描述

让我们假设一个表有很多列并且一个 Temporal 表正在记录它的历史。当它发生变化时,我需要知道一个字段。

数字 版本开始日期
991281 2021-11-12 08:27:11
991281 2021-11-12 08:20:11
无效的 2021-11-12 07:20:11
无效的 2021-11-12 06:20:11
771281 2021-11-11 08:26:11
无效的 2021-11-11 08:25:11
661281 2021-11-10 08:24:11
无效的 2021-11-10 08:22:11
661281 2021-11-10 08:21:11
551281 2021-11-09 08:20:11

我需要获取每个值,以及它改变的那一刻。我还需要知道它是否被设置为 NULL,所以这个查询没有给出我需要的。

SELECT
    Number,
    MIN(VersionStartDate) [Date]
FROM _TABLE_ 
GROUP BY
    Number
ORDER BY
    [Date] DESC

结果应该是

数字 版本开始日期
991281 2021-11-12 08:20:11
无效的 2021-11-12 06:20:11
771281 2021-11-11 08:26:11
无效的 2021-11-11 06:25:11
661281 2021-11-10 08:24:11
无效的 2021-11-10 08:22:11
661281 2021-11-10 08:21:11
551281 2021-11-09 08:20:11

标签: sqlsql-servertsqlgaps-and-islands

解决方案


与我开始研究后出现的 JMabee 非常相似,但可能更简单一些:

CREATE TABLE #d (Number INT, VersionStartDate DATETIME);
INSERT INTO #d(Number, VersionStartDate) 
VALUES
(991281 ,'2021-11-12T08:27:11'),
(991281 ,'2021-11-12T08:20:11'),
(NULL   ,'2021-11-12T07:20:11'),
(NULL   ,'2021-11-12T06:20:11'),
(771281 ,'2021-11-11T08:26:11'),
(NULL   ,'2021-11-11T08:25:11'),
(661281 ,'2021-11-10T08:24:11'),
(NULL   ,'2021-11-10T08:22:11'),
(661281 ,'2021-11-10T08:21:11'),
(551281 ,'2021-11-09T08:20:11');

WITH cte AS
(
    SELECT  Number,
            VersionStartDate,
            LAG(Number, 1) OVER (ORDER BY VersionStartDate) AS PrevNumber
    FROM    #d
)
SELECT      cte.Number,
            cte.VersionStartDate
FROM        cte
WHERE       ISNULL(cte.Number, -1) <> ISNULL(cte.PrevNumber, -1)
ORDER BY    cte.VersionStartDate DESC;

推荐阅读