내가 End
독점하고 주어진 간격이 중복되지 않는, Start
이 포함 된 것으로 가정합니다.
CTE_Number
은 숫자 표입니다. 여기에 즉시 생성됩니다. 내 데이터베이스에 영구 테이블로 가지고 있습니다.
CTE_T1
및 CTE_T2
은 숫자 표를 사용하여 각 간격을 해당 행 수로 확장합니다. Type1
및 Type2
위해 예를 들어, 간격 [2,5)
이 두번 수행 Values
2
3
4
와 행을 생성한다.
에 대한 결과는 Value
에 함께 FULL JOINed
입니다.
마지막으로 갭 - 아일랜드 통과 그룹/붕괴 간격 뒤로.
단계별로 CTE-by-CTE 쿼리를 실행하고 중간 결과를 검사하여 작동 방식을 이해합니다.
샘플 데이터
는 I 값 사이의 갭이있을 때 한 경우를 설명하기 위해 몇 행을 추가했다.
DECLARE @Table1 TABLE
([Start] int, [End] int, [Type1] varchar(4), [Type2] varchar(4))
;
INSERT INTO @Table1 ([Start], [End], [Type1], [Type2]) VALUES
(0, 2, 'L', NULL),
(2, 3, NULL, 'S'),
(2, 5, 'L', NULL),
(3, 5, NULL, 'S'),
(5, 7, 'L', NULL),
(5, 8, NULL, 'S'),
(7, 10, 'L', NULL),
(11, 12, NULL, 'S'),
(15, 20, 'L', NULL),
(15, 20, NULL, 'S');
쿼리
WITH
e1(n) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
) -- 10
,e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 AS b) -- 10*10
,e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2) -- 10*100
,CTE_Numbers
AS
(
SELECT ROW_NUMBER() OVER (ORDER BY n) AS Number
FROM e3
)
,CTE_T1
AS
(
SELECT
T1.[Start] + CA.Number - 1 AS Value
,T1.Type1
FROM
@Table1 AS T1
CROSS APPLY
(
SELECT TOP(T1.[End] - T1.[Start]) CTE_Numbers.Number
FROM CTE_Numbers
ORDER BY CTE_Numbers.Number
) AS CA
WHERE
T1.Type1 IS NOT NULL
)
,CTE_T2
AS
(
SELECT
T2.[Start] + CA.Number - 1 AS Value
,T2.Type2
FROM
@Table1 AS T2
CROSS APPLY
(
SELECT TOP(T2.[End] - T2.[Start]) CTE_Numbers.Number
FROM CTE_Numbers
ORDER BY CTE_Numbers.Number
) AS CA
WHERE
T2.Type2 IS NOT NULL
)
,CTE_Values
AS
(
SELECT
ISNULL(CTE_T1.Value, CTE_T2.Value) AS Value
,CTE_T1.Type1
,CTE_T2.Type2
,ROW_NUMBER() OVER (ORDER BY ISNULL(CTE_T1.Value, CTE_T2.Value)) AS rn
FROM
CTE_T1
FULL JOIN CTE_T2 ON CTE_T2.Value = CTE_T1.Value
)
,CTE_Groups
AS
(
SELECT
Value
,Type1
,Type2
,rn
,ROW_NUMBER() OVER
(PARTITION BY rn - Value, Type1, Type2 ORDER BY Value) AS rn2
FROM CTE_Values
)
SELECT
MIN(Value) AS [Start]
,MAX(Value) + 1 AS [End]
,Type1
,Type2
FROM CTE_Groups
GROUP BY rn-rn2, Type1, Type2
ORDER BY [Start];
결과
+-------+-----+-------+-------+
| Start | End | Type1 | Type2 |
+-------+-----+-------+-------+
| 0 | 2 | L | NULL |
| 2 | 8 | L | S |
| 8 | 10 | L | NULL |
| 11 | 12 | NULL | S |
| 15 | 20 | L | S |
+-------+-----+-------+-------+
는 그 ([간격 포장] http://blogs.solidq.com/en/sqlserver/packing- 보인다 간격 /)을 Itzik Ben-Gan이 사용할 수 있습니다. –
링크는 좋지만 모든 SQL은 SQL 2008R2와 호환되지 않습니다 (우리는 FLOOR 등을 사용할 수 없습니다). – Harry