如何使用“GROUP BY”在单个查询中查找 SQL 中最高和第二高的条目?

Posted

技术标签:

【中文标题】如何使用“GROUP BY”在单个查询中查找 SQL 中最高和第二高的条目?【英文标题】:How to find the highest and second highest entry in SQL in a single query using `GROUP BY`? 【发布时间】:2021-12-25 06:34:54 【问题描述】:

假设这是提供的表格。

PID TID Type Freq
1 1 A 3
1 1 A 2
1 1 A 1
1 1 B 3
1 2 A 4
1 2 B 5

我想写一个查询来得到这样的输出。

PID TID Type Max_Freq_1 Max_Freq_2
1 1 A 3 2
1 1 B 3 NULL
1 2 A 4 NULL
1 2 B 5 NULL

也就是说,给定PIDTIDType 的组合,最高频率和次高频率是多少?如果表中没有足够数量的条目,则将第二高设置为NULL

【问题讨论】:

【参考方案1】:

如果您的数据库可以使用窗口函数,那么可以通过 DENSE_RANK 函数计算前 2 个 Freq。

SELECT PID, TID, Type
, MAX(CASE WHEN Rnk = 1 THEN Freq END) AS Max_Freq_1
, MAX(CASE WHEN Rnk = 2 THEN Freq END) AS Max_Freq_2
FROM
(
    SELECT PID, TID, Type, Freq
    , DENSE_RANK() OVER (PARTITION BY PID, TID, Type ORDER BY Freq DESC) AS Rnk
    FROM YourTable t
) q
GROUP BY PID, TID, Type
ORDER BY PID, TID, Type
pid tid type max_freq_1 max_freq_2
1 1 A 3 2
1 1 B 3 null
1 2 A 4 null
1 2 B 5 null

如果 ROW_NUMBER 不可用,请试试这个。

SELECT PID, TID, Type
, MAX(CASE WHEN Rnk = 1 THEN Freq END) AS Max_Freq_1
, MAX(CASE WHEN Rnk = 2 THEN Freq END) AS Max_Freq_2
FROM
(
    SELECT t1.PID, t1.TID, t1.Type, t1.Freq
    , COUNT(DISTINCT t2.Freq) AS Rnk
    FROM YourTable t1
    LEFT JOIN YourTable t2 
      ON t2.PID = t1.PID
     AND t2.TID = t1.TID
     AND t2.Type = t1.Type
     AND t2.Freq >= t1.Freq
    GROUP BY t1.PID, t1.TID, t1.Type, t1.Freq
) q
GROUP BY PID, TID, Type
ORDER BY PID, TID, Type

dbfiddle here

上的演示

【讨论】:

【参考方案2】:

这是我在 PostgreSQL 上提出的。使用 row_number 之类的窗口函数是获得所需结果的最简单方法。

with t as (
    select *, row_number() over (partition by pid, tid, "type" order by freq desc) as r 
    from test_so 
) select pid, tid, "type", max(case when r = 1 then freq end) as "highest", max(case when r = 2 then freq end) as "second_highest" 
    from t 
    group by pid, tid, "type"

【讨论】:

以上是关于如何使用“GROUP BY”在单个查询中查找 SQL 中最高和第二高的条目?的主要内容,如果未能解决你的问题,请参考以下文章

如何在mongodb的单个查询中添加具有不同条件输出的Multiple Group By?

mysql 可以group by 两个字段吗

mysql group by 能用到索引么

在 group by 中使用 datetime 日期并在单个 SELECT 中使用 order by 与使用子查询

SQL重复记录查询-count与group by having结合查询重复记录

【MySQL】分组查询(GROUP BY)