Sql server 根据列的顺序跟踪SqlServer中的更改或分组,如Excel中的小计

Sql server 根据列的顺序跟踪SqlServer中的更改或分组,如Excel中的小计,sql-server,Sql Server,我有一张这样的桌子: CREATE TABLE dbo.Samples ( Id INT PRIMARY KEY, A INT NOT NULL, B INT NOT NULL, C INT NOT NULL, D

我有一张这样的桌子:

CREATE TABLE dbo.Samples
(
    Id                  INT             PRIMARY KEY,
    A                   INT             NOT NULL,
    B                   INT             NOT NULL,
    C                   INT             NOT NULL,
    D                   INT             NOT NULL,
)
GO
INSERT INTO dbo.Samples
        ( Id, A, B, C, D )
SELECT 1, 10, 10, 10, 10 UNION
SELECT 2, 10, 10, 11, 10 UNION
SELECT 3, 11, 10, 11, 10 UNION
SELECT 4, 11, 10, 11, 11 UNION
SELECT 5, 10, 10, 11, 11 
1  10   10  10  10
3  11   10  11  10
5  10   10  11  11
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
我正在寻找一个显示和跟踪此表中两列a和B的更改历史的查询。 结果应该是这样的:

CREATE TABLE dbo.Samples
(
    Id                  INT             PRIMARY KEY,
    A                   INT             NOT NULL,
    B                   INT             NOT NULL,
    C                   INT             NOT NULL,
    D                   INT             NOT NULL,
)
GO
INSERT INTO dbo.Samples
        ( Id, A, B, C, D )
SELECT 1, 10, 10, 10, 10 UNION
SELECT 2, 10, 10, 11, 10 UNION
SELECT 3, 11, 10, 11, 10 UNION
SELECT 4, 11, 10, 11, 11 UNION
SELECT 5, 10, 10, 11, 11 
1  10   10  10  10
3  11   10  11  10
5  10   10  11  11
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
因为在Id为1、3和5的记录中,a列或B列发生了变化。 我对这个问题有一个不完整的解决方案:

WITH cte
AS
(
    SELECT TOP 1 1 HasChange, * FROM Samples ORDER BY Id 
    UNION ALL
    SELECT IIF(cte.A != q.A OR cte.B != q.B, 1, 0), q.* FROM Samples q 
    INNER JOIN cte ON cte.Id + 1 = q.Id 
)
SELECT Id, A,B,C,D FROM cte WHERE HasChange = 1
但我想知道在SQLServer中是否有更好更简单的解决方案。 此外,当我使用大数据测试此查询时,会收到如下错误消息:

CREATE TABLE dbo.Samples
(
    Id                  INT             PRIMARY KEY,
    A                   INT             NOT NULL,
    B                   INT             NOT NULL,
    C                   INT             NOT NULL,
    D                   INT             NOT NULL,
)
GO
INSERT INTO dbo.Samples
        ( Id, A, B, C, D )
SELECT 1, 10, 10, 10, 10 UNION
SELECT 2, 10, 10, 11, 10 UNION
SELECT 3, 11, 10, 11, 10 UNION
SELECT 4, 11, 10, 11, 11 UNION
SELECT 5, 10, 10, 11, 11 
1  10   10  10  10
3  11   10  11  10
5  10   10  11  11
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
我的问题是:

  • 这个问题还有其他解决方案吗?如果有,性能提示是什么
  • 如果我应该使用CTE,我如何在超过一百万条记录的表上使用它
  • 一种选择是使用lag()

    示例

    Select *
     From ( 
            Select *
                  ,Flg = case when concat([A],[B])=lag(concat([A],[B]),1,'') over (Order by ID) then 0 else 1 end
             From  Samples
           ) A
     Where Flg=1
    
    返回

    一个选项是使用lag()

    示例

    Select *
     From ( 
            Select *
                  ,Flg = case when concat([A],[B])=lag(concat([A],[B]),1,'') over (Order by ID) then 0 else 1 end
             From  Samples
           ) A
     Where Flg=1
    
    返回


    非常感谢,我不知道sqlserver中的滞后功能。这是非常有用的,似乎是一个完整和完美的解决方案,这个问题。thanks@JafarElahi很乐意帮忙。窗口功能是非常宝贵的。非常值得您花时间熟悉它们:)非常感谢,我不知道sqlserver中的滞后函数。这是非常有用的,似乎是一个完整和完美的解决方案,这个问题。thanks@JafarElahi很乐意帮忙。窗口功能是非常宝贵的。值得你花时间去适应它们:)