SQL - 选择按多个字段分组的前 n 个,按计数排序

Posted

技术标签:

【中文标题】SQL - 选择按多个字段分组的前 n 个,按计数排序【英文标题】:SQL - Select top n grouped by multiple fields, ordered by count 【发布时间】:2018-05-17 19:39:31 【问题描述】:

我试图在按多个属性分组时查找前 n 条记录。我相信它与this problem 有关,但我很难根据我的情况调整所描述的解决方案。

为简化起见,我有一个包含列的表(did 是 device_id 的缩写):

id int
did int
dateVal dateTime

我正在尝试查找每一天的前 n 个设备 ID,其中行数最多。

例如(忽略id和dateTime的时间部分),

did dateVal
1   2017-01-01
1   2017-01-01
1   2017-01-01
2   2017-01-01
3   2017-01-01
3   2017-01-01

1   2017-01-02
1   2017-01-02
2   2017-01-02
2   2017-01-02
2   2017-01-02
3   2017-01-02

找到前 2 个将产生...

1, 2017-01-01
3, 2017-01-01
2, 2017-01-02
1, 2017-01-02

我目前的幼稚方法只给我所有日期的前 2 名。

--Using SQLite
select date(dateVal) || did 
from data 
group by date(dateVal), did
order by count(*) desc 
limit 2

我正在使用连接运算符,以便以后可以提取行。

我正在使用 SQLite,但任何一般的 SQL 解释都将不胜感激。

【问题讨论】:

【参考方案1】:

类似于this question,定义一个计算所需组的所有设备计数的 CTE,然后在WHERE ... IN 子查询中使用它,仅限于该日期的前 2 个设备:

WITH device_counts AS (
  SELECT did, date(dateval) AS dateval, COUNT(*) AS device_count
  FROM data
  GROUP BY did, date(dateval)
)
SELECT did, date(dateval) FROM device_counts DC_outer
WHERE did IN (
  SELECT did
  FROM device_counts DC_inner
  WHERE DC_inner.dateval = DC_outer.dateval
  GROUP BY did, date(dateval)
  ORDER BY DC_inner.device_count DESC LIMIT 2
)
ORDER BY date(dateval), did

【讨论】:

终于有时间试试这个方法了。相当肯定我正在处理的数据量导致查询挂起。我会让它通宵运行。同时,是否有可能以某种方式优化查询?比如可能不使用 date() 转换函数? 可能。 (did, date) 上的索引可能也会有所帮助。如果不知道每个表的 # 行以及您已经拥有的索引,很难说。【参考方案2】:

我使用 sql server 测试了查询

select top 2 did, dateVal
from (select *, count(*) as c
      from test
      group by did,dateVal) as t
order by t.c desc 

【讨论】:

以上是关于SQL - 选择按多个字段分组的前 n 个,按计数排序的主要内容,如果未能解决你的问题,请参考以下文章

mysql按字段分组并获取每个分组按照某个字段排序的前三条

sql group 后按分组数量的多少排序怎么写?

如何在单个 SQL 查询中使用多个计数和按条件分组

如何仅按某个列值的前几个字母对 SQL 查询进行分组?

按维度表计算的前 N ​​个

在sql中组合多个计数查询