我的表格数据如下:
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”等。
答案 0 :(得分:6)
对于评论中澄清的要求
group1的rownumbers可能是“1,1,2,2,3,4”,而group2则是 可能是“1,2,4,6”......较高的数字后跟较低的数字将是a 新组。
SQL Server 2012解决方案可能如下所示。
LAG
访问上一行,如果该行是新组的开头,则设置为1
的标记,否则设置为0
。<强>代码强>
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
假设ID
是聚集索引,则此计划对YourTable
进行一次扫描,并避免任何排序操作。
答案 1 :(得分:2)
如果id是真正的顺序,你可以这样做:
select t.*,
(id - rowNumber) as grp
from t
答案 2 :(得分:1)
您也可以使用递归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上的演示
答案 3 :(得分:1)
怎么样:
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()。