SQL Rank() 函数排除行
SQL Rank() function excluding rows
考虑一下我有以下 table。
ID value
1 100
2 200
3 200
5 250
6 1
我有以下查询,结果如下。我想从 rank 函数中排除值 200,但仍然必须返回该行。
SELECT
CASE WHEN Value = 200 THEN 0
ELSE DENSE_RANK() OVER ( ORDER BY VALUE DESC)
END AS RANK,
ID,
VALUE
FROM @table
RANK ID VALUE
1 5 250
0 2 200
0 3 200
4 1 100
5 6 1
但我想要的结果如下。如何实现?
RANK ID VALUE
1 5 250
0 2 200
0 3 200
2 1 100
3 6 1
目前无法排除 Dense Rank 中的 Val,除非你在 where 子句中过滤..这就是原因,你会得到低于结果
RANK ID VALUE
1 5 250
0 2 200
0 3 200
4 1 100
5 6 1
你需要先过滤一次,然后再做一个 union all
;with cte(id,val)
as
(
select 1, 100 union all
select 2, 200 union all
select 3, 200 union all
select 5, 250 union all
select 6, 1 )
select *, dense_rank() over (order by val desc)
from cte
where val<>200
union all
select 0,id,val from cte where val=200
你也可以试试这个:
SELECT ISNULL(R, 0) AS Rank ,t.id ,t.value
FROM tbl1 AS t
LEFT JOIN ( SELECT id ,DENSE_RANK() OVER ( ORDER BY value DESC ) AS R
FROM dbo.tbl1 WHERE value <> 200
) AS K
ON t.id = K.id
ORDER BY t.value DESC
您可以将排名拆分为您想要从排名中 include/exclude 的值的查询和 UNION ALL
结果,如下所示:
独立可执行示例:
CREATE TABLE #temp ( [ID] INT, [value] INT );
INSERT INTO #temp
( [ID], [value] )
VALUES ( 1, 100 ),
( 2, 200 ),
( 3, 200 ),
( 5, 250 ),
( 6, 1 );
SELECT *
FROM ( SELECT 0 RANK ,
ID ,
value
FROM #temp
WHERE value = 200 -- set rank to 0 for value = 200
UNION ALL
SELECT DENSE_RANK() OVER ( ORDER BY value DESC ) AS RANK ,
ID ,
value
FROM #temp
WHERE value != 200 -- perform ranking on records != 200
) t
ORDER BY value DESC ,
t.ID
DROP TABLE #temp
产生:
RANK ID value
1 5 250
0 2 200
0 3 200
2 1 100
3 6 1
如果需要,您可以修改语句末尾的顺序,我将其设置为产生您想要的结果。
如果 VAL 列不可为空,考虑到 NULL 是 ORDER BY .. DESC
中的最后一个值
select *, dense_rank() over (order by nullif(val,200) desc) * case val when 200 then 0 else 1 end
from myTable
order by val desc;
原题的解其实很接近。只需在 dense_rank 中添加一个分区子句就可以解决问题。
SELECT CASE
WHEN VALUE = 200 THEN 0
ELSE DENSE_RANK() OVER(
PARTITION BY CASE WHEN VALUE = 200 THEN 0 ELSE 1 END
ORDER BY VALUE DESC
)
END AS RANK
,ID
,VALUE
FROM @table
ORDER BY VALUE DESC;
'partition by' 为 dense_rank 创建单独的组,以便单独对这些组执行订单。这实质上意味着您同时创建两个等级,一个用于没有 200 值的组,一个用于只有 200 值的组。后一个在'case when'.
中设置为0
独立可执行示例:
DECLARE @table TABLE
(
ID INT NOT NULL PRIMARY KEY
,VALUE INT NULL
)
INSERT INTO @table
(
ID
,VALUE
)
SELECT 1, 100
UNION SELECT 2, 200
UNION SELECT 3, 200
UNION SELECT 5, 250
UNION SELECT 6, 1;
SELECT CASE
WHEN VALUE = 200 THEN 0
ELSE DENSE_RANK() OVER(
PARTITION BY CASE WHEN VALUE = 200 THEN 0 ELSE 1 END
ORDER BY VALUE DESC
)
END AS RANK
,ID
,VALUE
FROM @table
ORDER BY VALUE DESC;
RANK ID VALUE
1 5 250
0 2 200
0 3 200
2 1 100
3 6 1
考虑一下我有以下 table。
ID value
1 100
2 200
3 200
5 250
6 1
我有以下查询,结果如下。我想从 rank 函数中排除值 200,但仍然必须返回该行。
SELECT
CASE WHEN Value = 200 THEN 0
ELSE DENSE_RANK() OVER ( ORDER BY VALUE DESC)
END AS RANK,
ID,
VALUE
FROM @table
RANK ID VALUE
1 5 250
0 2 200
0 3 200
4 1 100
5 6 1
但我想要的结果如下。如何实现?
RANK ID VALUE
1 5 250
0 2 200
0 3 200
2 1 100
3 6 1
目前无法排除 Dense Rank 中的 Val,除非你在 where 子句中过滤..这就是原因,你会得到低于结果
RANK ID VALUE
1 5 250
0 2 200
0 3 200
4 1 100
5 6 1
你需要先过滤一次,然后再做一个 union all
;with cte(id,val)
as
(
select 1, 100 union all
select 2, 200 union all
select 3, 200 union all
select 5, 250 union all
select 6, 1 )
select *, dense_rank() over (order by val desc)
from cte
where val<>200
union all
select 0,id,val from cte where val=200
你也可以试试这个:
SELECT ISNULL(R, 0) AS Rank ,t.id ,t.value
FROM tbl1 AS t
LEFT JOIN ( SELECT id ,DENSE_RANK() OVER ( ORDER BY value DESC ) AS R
FROM dbo.tbl1 WHERE value <> 200
) AS K
ON t.id = K.id
ORDER BY t.value DESC
您可以将排名拆分为您想要从排名中 include/exclude 的值的查询和 UNION ALL
结果,如下所示:
独立可执行示例:
CREATE TABLE #temp ( [ID] INT, [value] INT );
INSERT INTO #temp
( [ID], [value] )
VALUES ( 1, 100 ),
( 2, 200 ),
( 3, 200 ),
( 5, 250 ),
( 6, 1 );
SELECT *
FROM ( SELECT 0 RANK ,
ID ,
value
FROM #temp
WHERE value = 200 -- set rank to 0 for value = 200
UNION ALL
SELECT DENSE_RANK() OVER ( ORDER BY value DESC ) AS RANK ,
ID ,
value
FROM #temp
WHERE value != 200 -- perform ranking on records != 200
) t
ORDER BY value DESC ,
t.ID
DROP TABLE #temp
产生:
RANK ID value
1 5 250
0 2 200
0 3 200
2 1 100
3 6 1
如果需要,您可以修改语句末尾的顺序,我将其设置为产生您想要的结果。
如果 VAL 列不可为空,考虑到 NULL 是 ORDER BY .. DESC
select *, dense_rank() over (order by nullif(val,200) desc) * case val when 200 then 0 else 1 end
from myTable
order by val desc;
原题的解其实很接近。只需在 dense_rank 中添加一个分区子句就可以解决问题。
SELECT CASE
WHEN VALUE = 200 THEN 0
ELSE DENSE_RANK() OVER(
PARTITION BY CASE WHEN VALUE = 200 THEN 0 ELSE 1 END
ORDER BY VALUE DESC
)
END AS RANK
,ID
,VALUE
FROM @table
ORDER BY VALUE DESC;
'partition by' 为 dense_rank 创建单独的组,以便单独对这些组执行订单。这实质上意味着您同时创建两个等级,一个用于没有 200 值的组,一个用于只有 200 值的组。后一个在'case when'.
中设置为0独立可执行示例:
DECLARE @table TABLE
(
ID INT NOT NULL PRIMARY KEY
,VALUE INT NULL
)
INSERT INTO @table
(
ID
,VALUE
)
SELECT 1, 100
UNION SELECT 2, 200
UNION SELECT 3, 200
UNION SELECT 5, 250
UNION SELECT 6, 1;
SELECT CASE
WHEN VALUE = 200 THEN 0
ELSE DENSE_RANK() OVER(
PARTITION BY CASE WHEN VALUE = 200 THEN 0 ELSE 1 END
ORDER BY VALUE DESC
)
END AS RANK
,ID
,VALUE
FROM @table
ORDER BY VALUE DESC;
RANK ID VALUE
1 5 250
0 2 200
0 3 200
2 1 100
3 6 1