选择 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)

在查询的输出上应用 DENSE_RANK()

max_val?255./max_val:0这个语句啥意思??

MIN() MAX() BigQuery - 意外行为

javascript MAX-VAL-IN列表

红包算法