按组排名 sql 服务器
Rank by groups sql server
问题看起来很简单,但我想不通,
这是 sql 服务器
what I have in a table : What I need as a output .
cksum id cksum id
-2162514679 204 -2162514679 204 1
-2162514679 207 -2162514679 207 1
-2162514679 215 -2162514679 215 1
-2162514679 218 -2162514679 218 1
-2162514679 221 -2162514679 221 1
-2160286363 257 -2160286363 257 2
-2160286363 260 -2160286363 260 2
-2160286363 332 -2160286363 332 2
-2162514679 335 -2162514679 335 3
-2162514679 338 -2162514679 338 3
-2126731931 348 -2126731931 348 4
-2126731931 387 -2126731931 387 4
table 按 id 排序,我需要一个跟在 id 列后面但对 cksum 进行分组的排名,请注意 cksum 可以 return 到以前的值但仍然有它的排名由于 ID(值 2162514679 就是这种情况,它在开头出现 5 次,第二次出现在下方,它们构成两个不同的等级)。我已经用了几个小时了,它看起来真的很愚蠢,比如将 row_number 与分区一起使用或使用 CTE 但不......找不到逻辑来做到这一点...... .有人知道答案吗?
这有点棘手。您可以使用一个技巧对 id 进行分组——行号的差异。然后你需要得到每个组的最小id,以确保最终排名顺序正确。然后你可以使用然后你可以使用密集排名:
select cksum, id, dense_rank() over (order by minid)
from (select t.*, min(id) over (partition by cksum, grp) as minid
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by cksum order by id)
) as grp
from table t
) t
) t;
这是一种不同的方法,它涉及模拟 LAG
window SQL Server 2008 R2 中不可用的功能:
;WITH CTE_RN AS (
SELECT cksum, id, ROW_NUMBER() OVER(ORDER BY id) AS rn
FROM Checksums
), CTE_LAG AS (
SELECT c1.cksum, c1.id, c1.rn,
(CASE WHEN c2.cksum IS NULL OR c1.cksum = c2.cksum THEN 0
ELSE 1
END) AS flag
FROM CTE_RN AS c1
LEFT JOIN CTE_RN AS c2 ON c1.rn = c2.rn+1
)
SELECT cksum, id, (SELECT SUM(flag)
FROM CTE_LAG AS t2
WHERE t2.rn <= t1.rn) + 1 AS [rank]
FROM CTE_LAG AS t1
CTE_LAG
returns 如下结果集(基于OP的样本数据):
cksum id rn flag
-------------------------
-2162514679 204 1 0
-2162514679 207 2 0
-2162514679 215 3 0
-2162514679 218 4 0
-2162514679 221 5 0
-2160286363 257 6 1
-2160286363 260 7 0
-2160286363 332 8 0
-2162514679 335 9 1
-2162514679 338 10 0
-2126731931 348 11 1
-2126731931 387 12 0
如果当前cksum
不等于前一个cksum
,字段flag
等于1,否则flag
等于0。
字段 rank
只是 flag
的 运行 总数。
问题看起来很简单,但我想不通, 这是 sql 服务器
what I have in a table : What I need as a output .
cksum id cksum id
-2162514679 204 -2162514679 204 1
-2162514679 207 -2162514679 207 1
-2162514679 215 -2162514679 215 1
-2162514679 218 -2162514679 218 1
-2162514679 221 -2162514679 221 1
-2160286363 257 -2160286363 257 2
-2160286363 260 -2160286363 260 2
-2160286363 332 -2160286363 332 2
-2162514679 335 -2162514679 335 3
-2162514679 338 -2162514679 338 3
-2126731931 348 -2126731931 348 4
-2126731931 387 -2126731931 387 4
table 按 id 排序,我需要一个跟在 id 列后面但对 cksum 进行分组的排名,请注意 cksum 可以 return 到以前的值但仍然有它的排名由于 ID(值 2162514679 就是这种情况,它在开头出现 5 次,第二次出现在下方,它们构成两个不同的等级)。我已经用了几个小时了,它看起来真的很愚蠢,比如将 row_number 与分区一起使用或使用 CTE 但不......找不到逻辑来做到这一点...... .有人知道答案吗?
这有点棘手。您可以使用一个技巧对 id 进行分组——行号的差异。然后你需要得到每个组的最小id,以确保最终排名顺序正确。然后你可以使用然后你可以使用密集排名:
select cksum, id, dense_rank() over (order by minid)
from (select t.*, min(id) over (partition by cksum, grp) as minid
from (select t.*,
(row_number() over (order by id) -
row_number() over (partition by cksum order by id)
) as grp
from table t
) t
) t;
这是一种不同的方法,它涉及模拟 LAG
window SQL Server 2008 R2 中不可用的功能:
;WITH CTE_RN AS (
SELECT cksum, id, ROW_NUMBER() OVER(ORDER BY id) AS rn
FROM Checksums
), CTE_LAG AS (
SELECT c1.cksum, c1.id, c1.rn,
(CASE WHEN c2.cksum IS NULL OR c1.cksum = c2.cksum THEN 0
ELSE 1
END) AS flag
FROM CTE_RN AS c1
LEFT JOIN CTE_RN AS c2 ON c1.rn = c2.rn+1
)
SELECT cksum, id, (SELECT SUM(flag)
FROM CTE_LAG AS t2
WHERE t2.rn <= t1.rn) + 1 AS [rank]
FROM CTE_LAG AS t1
CTE_LAG
returns 如下结果集(基于OP的样本数据):
cksum id rn flag
-------------------------
-2162514679 204 1 0
-2162514679 207 2 0
-2162514679 215 3 0
-2162514679 218 4 0
-2162514679 221 5 0
-2160286363 257 6 1
-2160286363 260 7 0
-2160286363 332 8 0
-2162514679 335 9 1
-2162514679 338 10 0
-2126731931 348 11 1
-2126731931 387 12 0
如果当前cksum
不等于前一个cksum
,字段flag
等于1,否则flag
等于0。
字段 rank
只是 flag
的 运行 总数。