Tsql SQL Server 2014中的折叠数据范围和重叠数据

Tsql SQL Server 2014中的折叠数据范围和重叠数据,tsql,sql-server-2014,Tsql,Sql Server 2014,我有一个表,表中的范围如下: ID ActionCode Group1 Type Low High 33 A 840 MM 000295800 000295899 34 A 840 MM 000295900 000295999 我需要将包含连续数据的两行折叠为一行,例如上面的示例 ActionCode Group1 Type Low High A

我有一个表,表中的范围如下:

ID  ActionCode  Group1  Type    Low         High
33  A           840     MM      000295800   000295899
34  A           840     MM      000295900   000295999
我需要将包含连续数据的两行折叠为一行,例如上面的示例

ActionCode  Group1  Type    Low         High
A           840     MM      000295800   000295999   
对于操作代码,Group1,键入

可能存在重叠的数据范围、之前的零等

样本表:

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

CREATE TABLE #TestTable(
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ActionCode] [char](1) NOT NULL,
    [Group1] [varchar](50) NOT NULL,
    [Type] [varchar](2) NULL,
    [Low] [varchar](50) NOT NULL,
    [High] [varchar](50) NOT NULL,
    CONSTRAINT [PK_#TestTable] PRIMARY KEY CLUSTERED ([ID] ASC)  
) 

GO

INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401299870','401299879')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','AA','401644000','401646999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401378000','401378999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401644000','401646999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401299970','401299979')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','400424000','400424999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401299990','401299996')
-- Ds
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('D','840','JJ','401198000','401198999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('D','840','JJ','401649000','401649999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401299997','401299997')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('D','840','JJ','401376000','401390999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401655000','401668999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','400411000','400411999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('D','840','JJ','400414000','400414999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401646000','401646999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('D','840','JJ','400413000','400413999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','JJ','401654000','401654999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','GG','522892000','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','GG','522892100','522892199')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','GG','522892400','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','AA','522892400','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','AA','522892300','522892399')
-- Different Types overlap range
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','AA','522892200','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','KK','522892000','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','KK','522892200','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','KK','522892300','522892399')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','KK','522892400','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','KK','522892100','522892199')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','GG','522892200','522892999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','GG','522892300','522892399')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','AA','522892100','522892199')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','356','AA','522892000','522892999')
-- Leading Zeros
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','MM','000295800','000295899')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','MM','000295900','000295999')
-- Overlap
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','NN','623295800','623295999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','NN','623295900','623295999')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','NN','623295900','623296099')
INSERT INTO #TestTable (ActionCode, Group1, Type, Low, High) VALUES ('A','840','NN','623296100','623296299')
GO


SELECT * FROM #TestTable ORDER BY Low
我可以使用递归CTE对一个小表执行此操作,但该表的行数略少于一百万行。但一旦我超过了一定的尺寸,就需要很长时间才能跑完。“分组”列上有一个索引

一定有办法很快做到这一点,我只是遇到了路障


^

我想您正在寻找这样的产品:

WITH CTE
AS
(
    SELECT  ActionCode,
            Group1,
            [Type],
            Low,
            High,
            next_low =  LEAD(low,1) OVER (PARTITION BY ActionCode,Group1,[Type] ORDER BY ID),
            next_high = LEAD(high,1) OVER (PARTITION BY ActionCode,Group1,[Type] ORDER BY ID)
    FROM #testTable
)

SELECT  ActionCode,
        Group1,
        [Type],
        Low,
        High
FROM CTE
WHERE       low != next_low 
        AND high!= next_high

我将假设你的低/高都是整数,所以可能需要对你所考虑的高低进行轻微的调整。

我还将假装没有看到相邻部分,在这种情况下,一个简单的组处理它:

SELECT
    ActionCode
    ,Group1
    ,Type
    ,min(convert(int,Low)) AS Low
    ,max(convert(int,High)) AS High
FROM #TestTable
GROUP BY
    ActionCode
    ,Group1
    ,Type
假设您对基于ID的每个相邻组都有相同的含义,这将成为一个典型的“间隙和孤岛”问题,可以通过与ID相比的行号来解决:

;WITH Src AS
    (
        SELECT
            *
            ,ID-ROW_NUMBER() OVER (PARTITION BY ActionCode, Group1,Type ORDER BY ID) AS ContiguousGroupID
        FROM #TestTable
    )

SELECT
    ContiguousGroupID
    ,ActionCode
    ,Group1
    ,Type
    ,min(ID) AS LowerIDBound
    ,max(ID) AS UpperIDBound
    ,min(convert(int,Low)) AS Low
    ,max(convert(int,High)) AS High
FROM Src
GROUP BY
    ContiguousGroupID
    ,ActionCode
    ,Group1
    ,Type
ORDER BY
    ContiguousGroupID
    ,ActionCode
    ,Group1
    ,Type

几乎,不完全是这样,例如NN类型应该崩溃为623295900和623296299。我认为你走对了方向。。。我会努力做这个。。。我认为这是一个很好的垫脚石。