2015-06-18 42 views
0

我有一個範圍內的表中它如下:收起數據範圍和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   840  MM  000295800 000295999 

對於ActionCode,組1,類型...

有可以重疊的數據範圍,前述零等

樣品表:

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一張小桌子做到這一點,但表中有一個不到一百萬行。但是一旦我超過了一定的尺寸,運行需要很長時間。在「分組」列上有一個索引。

必須有辦法快速做到這一點,我只是遇到了障礙。

^

回答

0

我認爲你正在尋找的東西是這樣的:

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 
+0

差不多,不大,比如類型NN應該收縮到623295900和623296299.我想你'在正確的軌道上......我會努力工作......我認爲這是一個很好的步驟音。 –

0

我打算做一個假設,你的低/高均爲整數,所以可能需要稍作調整什麼你考慮高和低。

我還要假裝自己沒有看到相鄰的部分揭開序幕,在這種情況下,一個簡單的組處理它:

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