Return只在table中修改记录,使用T-SQL

Return only the modified records in a table, using T-SQL

我正在尝试 return 仅 table 中修改的记录,使用 T-SQL。

这是我到目前为止所做的:

 BEGIN
    IF OBJECT_ID('tempdb..#Test') IS NOT NULL
        DROP TABLE #Test

    CREATE TABLE #Test
        (SetName nvarchar(100),
        [Timestamp] datetime,
        Value smallint)

    INSERT INTO #Test VALUES('Alpha', GETDATE(), 1)
    INSERT INTO #Test VALUES('Alpha', GETDATE(), 0)
    INSERT INTO #Test VALUES('Alpha', GETDATE(), 1)
    INSERT INTO #Test VALUES('Beta', GETDATE(), 1)
    INSERT INTO #Test VALUES('Beta', GETDATE(), 1)
    INSERT INTO #Test VALUES('Beta', GETDATE(), 1)
    INSERT INTO #Test VALUES('Gamma', GETDATE(), 1)
    INSERT INTO #Test VALUES('Gamma', GETDATE(), 0)
    INSERT INTO #Test VALUES('Gamma', GETDATE(), 1)

    SELECT * FROM #Test

END;

结果:

SetName Timestamp               Value

Alpha   2022-05-23 12:58:41.100 1
Alpha   2022-05-23 12:58:41.101 0
Alpha   2022-05-23 12:58:41.102 1
Beta    2022-05-23 12:58:41.103 1
Beta    2022-05-23 12:58:41.104 1
Beta    2022-05-23 12:58:41.105 1
Gamma   2022-05-23 12:58:41.106 1
Gamma   2022-05-23 12:58:41.107 0
Gamma   2022-05-23 12:58:41.108 1

预期结果:

Alpha   2022-05-23 12:58:41.101 0 -- Changed from 1 to 0
Alpha   2022-05-23 12:58:41.102 1 -- Changed from 0 to 1
Gamma   2022-05-23 12:58:41.107 0 -- Changed from 1 to 0
Gamma   2022-05-23 12:58:41.108 1 -- Changed from 0 to 1

下面的语句return全部是0到1,1到0的记录,我不明白为什么:

;WITH cte AS
(
SELECT 
    SetName, [Timestamp], Value, lag(Value, 1, -1) OVER (ORDER BY [Timestamp]) AS LastValue
FROM #Test
) 

SELECT 
    SetName, [Timestamp], [Value]
FROM
    cte
WHERE value <> LastValue

此解决方案假设单个SetName的2行不能具有与Timestamp相同的值(2 行 SetName 的不同值是可以的)。

一种方法是使用间隙和孤岛将值分组,然后从数据中省略第0组:

WITH CTE AS(
    SELECT SetName,
           [Timestamp], --timestamp is a deprecrated synonym for rowversion; I don't recommend it's use as a column name
           [value],
           ROW_NUMBER() OVER (PARTITION BY SetName ORDER BY Timestamp) - 
           ROW_NUMBER() OVER (PARTITION BY SetName, [Value] ORDER BY Timestamp) AS Grp
    FROM #Test)
SELECT SetName,
       [Timestamp], --timestamp is a deprecrated synonym for rowversion; I don't recommend it's use as a column name
       [value]
FROM CTE
WHERE Grp != 0
ORDER BY [Timestamp];

db<>fiddle

如果 2 行 可以 具有相同的值,那么 希望 您有一个始终递增的值,您可以 use in the ORDER BY 作为出色地;否则你无法知道“第一”行是什么。

要跟踪整个数据集的变化,您几乎已经做到了,您只需使用 LastValue <> -1.

删除第一行
WITH CTE AS
(
SELECT 
    SetName, [Timestamp], Value, lag(Value, 1, -1) OVER (ORDER BY [Timestamp]) AS LastValue
FROM #Test
) 

SELECT 
    SetName, [Timestamp], [Value]
FROM
    CTE
WHERE value<>Lastvalue
AND Lastvalue<> -1; --Add this filter to remove the rows which doesn't have any Lag Value

跟踪 SetName 级别的更改。

WITH CTE AS
(
SELECT 
   SetName, [Timestamp], Value, Lag(Value, 1, -1) OVER (PARTITION BY SetName ORDER BY [Timestamp]) AS LastValue
FROM #Test
) 

SELECT 
    SetName, [Timestamp], [Value]
FROM
    CTE
WHERE Value<>LastValue
AND LastValue <> -1;

db<>fiddle: Try here

注意:从给定的数据集中,在 SetName 级别和整个数据集中修改的记录是相同的。

假设:每个时间戳值不同。