Sql 是否获取与某个值不同的所有连续行?

Sql 是否获取与某个值不同的所有连续行?,sql,sql-server,tsql,sql-server-2008,Sql,Sql Server,Tsql,Sql Server 2008,我正试着让我的头左右做这件事,因为它涉及到连续行的比较。我正在尝试将差异一定数量的值分组。例如,假设我有这个表: 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

我正试着让我的头左右做这件事,因为它涉及到连续行的比较。我正在尝试将差异一定数量的值分组。例如,假设我有这个表:

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
让我们假设我必须将所有不同于1的值进行分组,它们对于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,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

我将在一个大约3000万行的大表上执行此操作,因此我希望有一种更好的方法来处理任意值,例如,不只是相差1,还可以是2或3,稍后我将把它合并到一个过程中。关于我的方法是否没有bug,以及是否可以改进,有什么建议吗?

对于不同的情况,您可以使用不同的方法

;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

+1工作完美!一个快速的澄清:是否有一种自然的方式将其扩展到我所看到的小于或等于而不是绝对差的情况?也就是说,对于@Interval=2的情况,它也会在同一组中获得相差1的值。所以在本例中,它将8,3 8,4 8,5 8,6分为一组。@Legend-将不得不考虑这一组!我认为米凯尔的回答是基于低于或等于假设的。是的。我想是的。您的版本看起来有点简短和优雅:但是,谢谢您的帮助。今天我学了一门新技术+谢谢你抽出时间!这是我想要的。我会检查一下这个的性能然后回来。我的方法几乎相似,但我担心多个连接。
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