DENSE_RANK() 无重复
DENSE_RANK() without duplication
这是我的数据:
| col1 | col2 | denserank | whatiwant |
|------|------|-----------|-----------|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 2 | 2 | 2 |
| 4 | 2 | 2 | 2 |
| 5 | 1 | 1 | 3 |
| 6 | 2 | 2 | 4 |
| 7 | 2 | 2 | 4 |
| 8 | 3 | 3 | 5 |
这是我目前的查询:
SELECT col1, col2, DENSE_RANK() OVER (ORDER BY COL2) AS [denserank]
FROM [table1]
ORDER BY [col1] asc
我想要实现的是,每当 col2 的值发生变化时(即使该值本身被重用),我的 denserank 列都会 递增 。我实际上不能按我有 denserank 的列排序,所以那行不通)。有关示例,请参见 whatiwant
列。
有什么方法可以用 DENSE_RANK()
实现吗?或者有其他选择吗?
我认为这在纯粹 SQL 中使用一些间隙和孤岛技巧是可能的,但阻力最小的路径可能是使用会话变量结合 LAG()
来跟踪您何时计算出的密集等级变化值。在下面的查询中,我使用 @a
来跟踪密集排名的变化,当它发生变化时,这个变量递增 1。
DECLARE @a int
SET @a = 1
SELECT t.col1,
t.col2,
t.denserank,
@a = CASE WHEN LAG(t.denserank, 1, 1) OVER (ORDER BY t.col1) = t.denserank
THEN @a
ELSE @a+1 END AS [whatiwant]
FROM
(
SELECT col1, col2, DENSE_RANK() OVER (ORDER BY COL2) AS [denserank]
FROM [table1]
) t
ORDER BY t.col1
尝试使用 window 函数:
with t(col1 ,col2) as (
select 1 , 1 union all
select 2 , 1 union all
select 3 , 2 union all
select 4 , 2 union all
select 5 , 1 union all
select 6 , 2 union all
select 7 , 2 union all
select 8 , 3
)
select t.col1,
t.col2,
sum(x) over (
order by col1
) whatyouwant
from (
select t.*,
case
when col2 = lag(col2) over (
order by col1
)
then 0
else 1
end x
from t
) t
order by col1;
产生:
它执行单个 table 读取并按 col1 的递增顺序形成一组连续相等的 col2 值,然后在其上找到密集的排名。
x
:如果前一行的 col2 与本行的 col2 相同(按 col1
递增的顺序),则赋值为 0,否则为 1
whatyouwant
:通过对上一步生成的值 x
进行增量求和,按递增 col1
的顺序创建一组相等的 col2
值,并且这就是你的输出。
我会用这样的递归 cte 来做:
declare @Dept table (col1 integer, col2 integer)
insert into @Dept values(1, 1),(2, 1),(3, 2),(4, 2),(5, 1),(6, 2),(7, 2),(8, 3)
;with a as (
select col1, col2,
ROW_NUMBER() over (order by col1) as rn
from @Dept),
s as
(select col1, col2, rn, 1 as dr from a where rn=1
union all
select a.col1, a.col2, a.rn, case when a.col2=s.col2 then s.dr else s.dr+1 end as dr
from a inner join s on a.rn=s.rn+1)
col1, col2, dr from s
result:
col1 col2 dr
----------- ----------- -----------
1 1 1
2 1 1
3 2 2
4 2 2
5 1 3
6 2 4
7 2 4
8 3 5
仅当您的 col1 值不连续时才需要 ROW_NUMBER。如果是,您可以立即使用递归 cte
这是使用 SUM OVER(Order by)
window 聚合函数的一种方法
SELECT col1,Col2,
Sum(CASE WHEN a.prev_val = a.col2 THEN 0 ELSE 1 END) OVER(ORDER BY col1) AS whatiwant
FROM (SELECT col1,
col2,
Lag(col2, 1)OVER(ORDER BY col1) AS prev_val
FROM Yourtable) a
ORDER BY col1;
工作原理:
LAG
window 函数用于查找按 col1
排序的每一行的前一个 col2
SUM OVER(Order by)
只会在前一个 col2
不等于当前 col2
时增加数字
这是我的数据:
| col1 | col2 | denserank | whatiwant |
|------|------|-----------|-----------|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 2 | 2 | 2 |
| 4 | 2 | 2 | 2 |
| 5 | 1 | 1 | 3 |
| 6 | 2 | 2 | 4 |
| 7 | 2 | 2 | 4 |
| 8 | 3 | 3 | 5 |
这是我目前的查询:
SELECT col1, col2, DENSE_RANK() OVER (ORDER BY COL2) AS [denserank]
FROM [table1]
ORDER BY [col1] asc
我想要实现的是,每当 col2 的值发生变化时(即使该值本身被重用),我的 denserank 列都会 递增 。我实际上不能按我有 denserank 的列排序,所以那行不通)。有关示例,请参见 whatiwant
列。
有什么方法可以用 DENSE_RANK()
实现吗?或者有其他选择吗?
我认为这在纯粹 SQL 中使用一些间隙和孤岛技巧是可能的,但阻力最小的路径可能是使用会话变量结合 LAG()
来跟踪您何时计算出的密集等级变化值。在下面的查询中,我使用 @a
来跟踪密集排名的变化,当它发生变化时,这个变量递增 1。
DECLARE @a int
SET @a = 1
SELECT t.col1,
t.col2,
t.denserank,
@a = CASE WHEN LAG(t.denserank, 1, 1) OVER (ORDER BY t.col1) = t.denserank
THEN @a
ELSE @a+1 END AS [whatiwant]
FROM
(
SELECT col1, col2, DENSE_RANK() OVER (ORDER BY COL2) AS [denserank]
FROM [table1]
) t
ORDER BY t.col1
尝试使用 window 函数:
with t(col1 ,col2) as (
select 1 , 1 union all
select 2 , 1 union all
select 3 , 2 union all
select 4 , 2 union all
select 5 , 1 union all
select 6 , 2 union all
select 7 , 2 union all
select 8 , 3
)
select t.col1,
t.col2,
sum(x) over (
order by col1
) whatyouwant
from (
select t.*,
case
when col2 = lag(col2) over (
order by col1
)
then 0
else 1
end x
from t
) t
order by col1;
产生:
它执行单个 table 读取并按 col1 的递增顺序形成一组连续相等的 col2 值,然后在其上找到密集的排名。
x
:如果前一行的 col2 与本行的 col2 相同(按col1
递增的顺序),则赋值为 0,否则为 1whatyouwant
:通过对上一步生成的值x
进行增量求和,按递增col1
的顺序创建一组相等的col2
值,并且这就是你的输出。
我会用这样的递归 cte 来做:
declare @Dept table (col1 integer, col2 integer)
insert into @Dept values(1, 1),(2, 1),(3, 2),(4, 2),(5, 1),(6, 2),(7, 2),(8, 3)
;with a as (
select col1, col2,
ROW_NUMBER() over (order by col1) as rn
from @Dept),
s as
(select col1, col2, rn, 1 as dr from a where rn=1
union all
select a.col1, a.col2, a.rn, case when a.col2=s.col2 then s.dr else s.dr+1 end as dr
from a inner join s on a.rn=s.rn+1)
col1, col2, dr from s
result:
col1 col2 dr
----------- ----------- -----------
1 1 1
2 1 1
3 2 2
4 2 2
5 1 3
6 2 4
7 2 4
8 3 5
仅当您的 col1 值不连续时才需要 ROW_NUMBER。如果是,您可以立即使用递归 cte
这是使用 SUM OVER(Order by)
window 聚合函数的一种方法
SELECT col1,Col2,
Sum(CASE WHEN a.prev_val = a.col2 THEN 0 ELSE 1 END) OVER(ORDER BY col1) AS whatiwant
FROM (SELECT col1,
col2,
Lag(col2, 1)OVER(ORDER BY col1) AS prev_val
FROM Yourtable) a
ORDER BY col1;
工作原理:
LAG
window 函数用于查找按 col1
col2
SUM OVER(Order by)
只会在前一个 col2
不等于当前 col2