选择 max dense_rank() = value 的所有位置?
Posted
技术标签:
【中文标题】选择 max dense_rank() = value 的所有位置?【英文标题】:Select all where max dense_rank() = value? 【发布时间】:2019-08-28 06:31:38 【问题描述】:我有使用dense_rank 的代码,按ID 分区并按val2 排序。 我想选择任何给定 ID 的最大排名为 2 的所有行。
以下代码为初始步骤提供了正确的输出。
Select distinct
`account id`, `val2`, distinct_rank, observation_total
from ( Select
`account id`, `val2`, dense_rank()
over (partition by `account id` order by `val2` desc) as distinct_rank,
count(*)
over (partition by `account id` order by `val2` desc) as observation_total
from TABLE1 );
样本结果:
account id | val2 | distinct_rank
___________________________________
1 | a | 1
2 | a | 1
2 | b | 2
2 | c | 3
3 | d | 1
3 | e | 2
所以我需要一个查询,它只选择每个帐户 id 的最大 distinct_rank = 2 或其他值的行。
例如,如果 max distinct_rank per account id = 2,结果将是:
account id | val2 | distinct_rank
___________________________________
3 | d | 1
3 | e | 2
This is because account id = 3 has a max distinct_rank of 2.
我知道如何选择 max rank = 2 的位置,我可以只做一个查询,上面写着“select * where account id in a subquery that grab all with max distinct_rank = 2”,但我觉得可能会有更好的/ 更高效的方式?
【问题讨论】:
该代码(带有可怕的反引号)对于 SQL Server 无效。看起来您使用的是 mysql,而不是 SQL Server 【参考方案1】:你可以试试下面-
with cte as
(
select
`account id`
,`val2`
, dense_rank() over (partition by `account id` order by `val2` desc) as distinct_rank
, count(*) over (partition by `account id` order by `val2` desc) as observation_total
from TABLE1
)
select [account id],val2,distinct_rank from cte
where [account id] in
(select [account id] from cte group by [account id] having max(distinct_Rank)=2)
【讨论】:
【参考方案2】:可以使用max
解析函数:
select `account id`, `val2`, distinct_rank, observation_total from
(select distinct
`account id`
, `val2`
, distinct_rank
, observation_total
, max(distinct_rank) over (partition by `account id`) as max_distinct_rank
from (
select
`account id`
,`val2`
, dense_rank() over (partition by `account id` order by `val2` desc) as distinct_rank
, count(*) over (partition by `account id` order by `val2` desc) as observation_total
from TABLE1
))
干杯!!
【讨论】:
【参考方案3】:目前没有办法通过与发起它的SELECT
相同范围内的窗口函数的结果来过滤行。
这意味着您不能执行以下操作:
SELECT
WindowResult = DENSE_RANK() OVER (<OverClause>)
FROM
SomeTable AS T
WHERE
DENSE_RANK() OVER (<OverClause>) = 1
Msg 4108, Level 15, State 1, Line 6 窗口函数只能 出现在 SELECT 或 ORDER BY 子句中。
在不更改您当前使用的功能/逻辑的情况下进行过滤的唯一方法是将其包装在 CTE 或子查询中并引用结果,正如您所提到的。
;WITH Subquery AS
(
SELECT
WindowResult = DENSE_RANK() OVER (<OverClause>)
FROM
SomeTable AS T
)
SELECT
S.*
FROM
Subquery AS S
WHERE
S.WindowResult = 1
但是,您可以尝试找到一种不同的方法来过滤掉不需要窗口函数的行,并避免使用子查询。为此,我们需要您的原始表格样本数据和您正在寻找的结果。
【讨论】:
【参考方案4】:试试CROSS APPLY 运算符:
select
*
from table1 a
cross apply(
select count(distinct val2) dist_qnt
from table1 b where b.[account id] = a.[account id]
) ca
where ca.dist_qnt = 2;
或者使用这个post中的方法。
select *
from (
select
*,
dense_rank() over(
partition by [account id] order by val2
) +
dense_rank() over(
partition by [account id] order by val2 desc
) - 1 as dist_qnt
from table1
) sq
where dist_qnt = 2;
但要考虑 NULL 值。
SQL Fiddle 上的演示。
【讨论】:
以上是关于选择 max dense_rank() = value 的所有位置?的主要内容,如果未能解决你的问题,请参考以下文章
⭐️ LeetCode解题系列 ⭐️ 176. 第二高的薪水(Oracle dense_rank 和 max)