2011-10-21 6 views
6

연속적인 행의 비교가 포함되어 있기 때문에이 일을하면서 머리를 쓰려고합니다. 특정 숫자만큼 다른 값을 그룹화하려고합니다. 예를 들어, 우리는 내가이 테이블이 있다고 가정 해 봅시다 :모든 값이 다른 모든 연속적인 행을 가져 오는 중입니까?

CREATE TABLE #TEMP (A int, B int) 

-- Sample table 
INSERT INTO #TEMP VALUES 
(3,1), 
(3,2), 
(3,3), 
(3,4), 
(5,1), 
(6,1), 
(7,2), 
(8,3), 
(8,4), 
(8,5), 
(8,6) 

SELECT * FROM #TEMP 

DROP TABLE #TEMP 

을 그리고 우리가 내가 그룹에 그럼 난 같은 출력을 얻기 위해 노력하고 있어요 A.에 대해 동일한 값을 갖는 한 차이가 모든 값을 가정 해 봅시다 : 그들이 다르기 때문에

A B GroupNo 
3 1 1 
3 2 1 
3 3 1 
3 4 1 
5 1 2 
6 1 3 
7 2 4 
8 3 5 
8 4 5 
8 5 5 
8 6 5 

(3,1) (3,2) (3,3) (3,4)(8,3) (8,4) (8,5) (8,6)는 내가 처음 내 시도를 표시하는 값 1로 같은 그룹에 투입되었습니다

CREATE TABLE #TEMP (A int, B int) 

-- Sample table 
INSERT INTO #TEMP VALUES 
(3,1), (3,2), (3,3), (3,4), (5,1), (6,1), (7,2), 
(8,3), (8,4), (8,5), (8,6) 

-- Assign row numbers and perform a left join 
-- so that we can compare consecutive rows 
SELECT ROW_NUMBER() OVER (ORDER BY A ASC) ID, * 
INTO #TEMP2 
FROM #TEMP 

;WITH CTE AS 
(
    SELECT X.A XA, X.B XB, Y.A YA, Y.B YB 
    FROM #TEMP2 X 
    LEFT JOIN #TEMP2 Y 
    ON X.ID = Y.ID - 1 
    WHERE X.A = Y.A AND 
    X.B = Y.B - 1 
) 
SELECT XA, XB 
INTO #GROUPS 
FROM CTE 
UNION 
SELECT YA, YB 
FROM CTE 
ORDER BY XA ASC 

-- Finally assign group numbers 
SELECT X.XA, X.XB, Y.GID 
FROM #GROUPS X 
INNER JOIN 
(SELECT XA, ROW_NUMBER() OVER (ORDER BY XA ASC) GID 
    FROM #GROUPS Y 
    GROUP BY XA 
) Y 
ON X.XA = Y.XA 

DROP TABLE #TEMP 
DROP TABLE #TEMP2 
DROP TABLE #GROUPS 
난에이 일을하고있을 것입니다

큰 테이블 (약 3 천만 행) 그래서 임의의 값 (예를 들어, 단지 1에 의해 다르지 않지만, 2 또는 3 내가 나중에 절차에 통합됩니다)에 대한이 일을 더 나은 방법이되기를 바랐다. 내 접근 방식에 버그가 없는지 그리고 개선 될 수 있는지에 대한 제안 사항이 있습니까?

가 하나 다를 경우를 들어

답변

2
declare @Diff int = 1 

;with C as 
(
    select A, 
     B, 
     row_number() over(partition by A order by B) as rn 
    from #TEMP 
), 
R as 
(
    select C.A, 
     C.B, 
     1 as G, 
     C.rn 
    from C 
    where C.rn = 1 
    union all 
    select C.A, 
     C.B, 
     G + case when C.B-R.B <= @Diff 
       then 0 
       else 1 
      end, 
     C.rn 
    from C 
    inner join R 
     on R.rn + 1 = C.rn and 
      R.A = C.A  
) 
select A, 
     B, 
     dense_rank() over(order by A, G) as G 
from R 
order by A, G 
+0

+1 시간 내 주셔서 감사합니다. 이것은 내가 원하는 것처럼 작동합니다. 나는 이것에 성과를 검사하고 돌아올 것이다. 내 접근 방식은 거의 유사했지만 다중 조인이 걱정되었습니다. – Legend

3

당신은

;WITH T AS 
(
SELECT *, 
     B - DENSE_RANK() OVER (PARTITION BY A ORDER BY B) AS Grp 
FROM #TEMP 
) 
SELECT A, 
     B, 
     DENSE_RANK() OVER (ORDER BY A,Grp) AS GroupNo 
FROM T 
ORDER BY A, Grp 

을 사용할 수 있습니다 그리고 더 일반적으로

DECLARE @Interval INT = 2 

;WITH T AS 
(
SELECT *, 
     B/@Interval - DENSE_RANK() OVER (PARTITION BY A, B%@Interval ORDER BY B) AS Grp 
FROM #TEMP 
) 
SELECT A, 
     B, 
     DENSE_RANK() OVER (ORDER BY A, B%@Interval,Grp) AS GroupNo 
FROM T 
ORDER BY A, GroupNo 
+0

일을 아주 잘 생각 대답, 완벽하게 작동합니다. – Lamak

+0

+1 완벽하게 작동합니다! 한 가지 간단한 설명 :이 차이점을 내가 절대 차이 대신에 같거나 그보다 작게 보는 경우로 확장하는 자연스러운 방법이 있습니까? 즉,'@Interval = 2'의 경우, 하나씩 다른 값을 동일한 그룹으로 가져옵니다. 따라서이 경우'(8,3) (8,4) (8,5) (8,6)'을 하나의 그룹으로 묶습니다. – Legend

+0

@Legend - 저것에 대해 생각해야 할 것입니다! 나는 미카엘의 대답이 평범한 것에 지나지 않는다고 생각한다. –

관련 문제