在 GROUP BY 中按行数获取前 N 行
Posted
技术标签:
【中文标题】在 GROUP BY 中按行数获取前 N 行【英文标题】:Get the top N rows by row count in GROUP BY 【发布时间】:2021-11-27 17:32:38 【问题描述】:我正在查询一个记录表,以查找哪些用户是我对某些记录类型的主要记录创建者。我的查询的基本起点如下所示:
SELECT recordtype, createdby, COUNT(*)
FROM recordtable
WHERE recordtype in (...)
GROUP BY recordtype, createdby
ORDER BY recordtype, createdby DESC
但是有很多用户创建了记录 - 我想进一步缩小范围。
我添加了HAVING COUNT(*) > ...
,但有些记录类型只有几条记录,而另一些则有数百条记录。如果我这样做HAVING COUNT(*) > 10
,我不会看到所有 9 条“XYZ”类型的记录都是由同一个人创建的,但我必须滚动浏览每个人,这些人只创建了 15、30、50 等3,500 条“ABC”类型的记录。
我只想要每种记录类型的前 5、10 名左右的创建者。
我发现了一些解决问题的“选择组中前 N 个”部分的问题,但我不知道如何将它们应用于我需要的内容。我能找到的答案是“排名依据”列是存储在表中的值,而不是聚合值。
(例如:“每个国家/地区人口最多的城市是什么?”,数据如下所示:)
Country City Population United States New York 123456789 United States Chicago 123456789 France Paris 123456789
我不知道如何应用我见过的用于回答这个问题的方法(主要是row_number()
)来获得COUNT(*)
的前 N 个。
【问题讨论】:
【参考方案1】:这是一种方法,可以在每组中获取前 10 行:
select * from(
select *, row_number() over (partition by recordtype order by cnt desc) rn
from (
SELECT recordtype, createdby, COUNT(*) cnt
FROM recordtable
WHERE recordtype in (...)
GROUP BY recordtype, createdby
)t
)t where rn <= 10
【讨论】:
做到了。谢谢!我确实注意到一个错字:partition recordtype by
.【参考方案2】:
如果我理解得很好,您想获得数量最多的前 N 条记录。您可以使用这样的子查询来实现这一点(我想您正在使用 mysql 或 PostGRESQL 或 db2,在其他数据库引擎中,限制和偏移量可能会有所不同,例如在 sqlserver 中通过 select top n * from...
SELECT A.recordtype, A.createdby, A.total FROM (
SELECT recordtype, createdby, COUNT(*) as total
FROM recordtable
WHERE recordtype in (...)
GROUP BY recordtype, createdby
) AS A ORDER BY recordtype, createdby, total DESC
LIMIT 10 OFFSET 0
limit 是你想要在结果页中的记录数,offset 是在进入结果页之前要跳过的记录数。
如果你使用 sqlserver,它可能看起来像这样(还有一种方法可以应用偏移量,你可以看看这里SQL Server OFFSET and LIMIT)
SELECT TOP 10 A.recordtype, A.createdby, A.total FROM (
SELECT recordtype, createdby, COUNT(*) as total
FROM recordtable
WHERE recordtype in (...)
GROUP BY recordtype, createdby
) AS A ORDER BY recordtype, createdby, total DESC
对于分组结果,您可以查看此帖子http://www.silota.com/docs/recipes/sql-top-n-group.html
所以要分组获取前 10 条记录,不仅是第一个我混合了这个答案,还有下面的链接和@eshirvana 的方法
SELECT * FROM (
SELECT *, row_number() OVER (PARTITION recordtype BY ORDER BY total DESC) rn
FROM (
SELECT recordtype, createdby, COUNT(*) as total
FROM recordtable
WHERE recordtype in (...)
GROUP BY recordtype, createdby
) t
) t WHERE total <= 10
【讨论】:
第一个查询没有给出我正在寻找的结果。我想要 每个组中的前 N 条记录。所有这些查询给我的是一种记录类型的前 10 个创建者,按用户名的字母顺序排列。该链接也是我试图弄清楚的一个链接,但它没有回答“top N by count”部分。 我更新了答案以适应@eshirvana 的答案以完成答案。以上是关于在 GROUP BY 中按行数获取前 N 行的主要内容,如果未能解决你的问题,请参考以下文章