簡體   English   中英

根據訂單對SQL結果進行分組

[英]Grouping SQL Results based on order

我有這樣的數據表:

ID     | RowNumber     | Data
------------------------------
1      | 1             | Data
2      | 2             | Data
3      | 3             | Data
4      | 1             | Data
5      | 2             | Data
6      | 1             | Data
7      | 2             | Data
8      | 3             | Data
9      | 4             | Data

我想對每組RowNumbers進行分組,以便我的結果是這樣的:

ID     | RowNumber     | Group | Data
--------------------------------------
1      | 1             | a     | Data
2      | 2             | a     | Data
3      | 3             | a     | Data
4      | 1             | b     | Data
5      | 2             | b     | Data
6      | 1             | c     | Data
7      | 2             | c     | Data
8      | 3             | c     | Data
9      | 4             | c     | Data

我知道每個組開始和停止的唯一方法是RowNumber重新開始。 我怎么能做到這一點? 它還需要相當高效,因為我需要這樣做的表有5200萬行。

附加信息

ID是真正的順序,但RowNumber可能不是。 我認為RowNumber總是以1開頭,但是例如group1的RowNumbers可以是“1,1,2,2,3,4”,而group2則可以是“1,2,4,6”等。

對於評論中澄清的要求

group1的rownumbers可以是“1,1,2,2,3,4”,而對於group2,它們可以是“1,2,4,6”......較高的數字后跟較低的數字將是一個新組。

SQL Server 2012解決方案可能如下所示。

  1. 如果該行是新組的開頭,則使用LAG訪問上一行並將標志設置為1否則設置為0
  2. 計算這些標志的運行總和以用作分組值。

WITH T1 AS
(
SELECT *,
       LAG(RowNumber) OVER (ORDER BY ID) AS PrevRowNumber
FROM YourTable
), T2 AS
(
SELECT *,
       IIF(PrevRowNumber IS NULL OR PrevRowNumber > RowNumber, 1, 0) AS NewGroup
FROM T1
)
SELECT ID,
        RowNumber,
        Data,
        SUM(NewGroup) OVER (ORDER BY ID 
                            ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS  Grp
FROM T2

SQL小提琴

假設ID是聚集索引,則此計划對YourTable一次掃描,並避免任何排序操作。

計划

如果id是真正的順序,你可以這樣做:

select t.*,
       (id - rowNumber) as grp
from t

您也可以使用遞歸CTE

 ;WITH cte AS
 (       
  SELECT ID, RowNumber, Data, 1 AS [Group]
  FROM dbo.test1
  WHERE ID = 1
  UNION ALL
  SELECT t.ID, t.RowNumber, t.Data, 
         CASE WHEN t.RowNumber != 1 THEN c.[Group] ELSE c.[Group] + 1 END
  FROM dbo.test1 t JOIN cte c ON t.ID = c.ID + 1
  )
  SELECT *
  FROM cte

SQLFiddle上演示

怎么樣:

select ID, RowNumber, Data, dense_rank() over (order by grp) as Grp
from (
     select *, (select min(ID) from [Your Table] where ID > t.ID and RowNumber = 1) as grp
     from [Your Table] t
) t
order by ID

這應該適用於SQL 2005.如果您不關心連續數字,也可以使用rank()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM