MYSQL 求每个月的 topN 问题

2021-03-29 11:33:29 +08:00
 vegetableChick

有如下的一个表

months  contact   COUNT
202007  asdas      45
202007  maouse      1
202007  RORC YANG   1
202007  RORG        2
202007  ROR         5
202008  SARINA      6
202008  MBL         2
202008  MLT         2
...

我如何能获取到每个月的top2?

希望得到的结果:

months  contact   COUNT
202007  asdas      45
202007  ROR         5
202008  SARINA      6
202008  MBL         2
...

当前 mysql 版本 5.6

请各位大佬帮忙看一下, 感谢!

2252 次点击
所在节点    酷工作
18 条回复
uselessVisitor
2021-03-29 14:25:46 +08:00
select * from a A where (select cout(*) from a B where A.months = B.months and A.count >= B.count) <= 2
uselessVisitor
2021-03-29 14:26:26 +08:00
count(*) 拼错了,还有你发错分区了吧。。
Nostalgiaaaa
2021-03-29 14:29:32 +08:00
SELECT *
FROM
(SELECT *,
ROW_NUMBER() over(partition by months
ORDER BY COUNT desc) ranks
FROM table ) a
WHERE a.ranks IN (1, 2)
ahmcsxcc
2021-03-29 14:31:25 +08:00
@Nostalgiaaaa #3 mysql 5.6 不支持这个语法
uselessVisitor
2021-03-29 15:32:25 +08:00
@ahmcsxcc 是的,mysql 这个需求比较难弄啊,感觉要写存储过程。。不然就要在代码里写了。。还是 PgSql 函数多
vegetableChick
2021-03-29 15:32:56 +08:00
@beichenhpy 感谢回复, 但是好像是空结果
vegetableChick
2021-03-29 15:33:31 +08:00
@Nostalgiaaaa 谢谢回复, 我的 mysql 版本比较旧了 还是 5.6
uselessVisitor
2021-03-29 16:03:17 +08:00
@vegetableChick
-- part 为 month 对应用谁分组
select z.month,z.count,z.rank
from
(select
x.*,
@rownum := @rownum + 1,
if(@part = x.month,
@r := @r + 1,
@r := 1) as rank,
@part := x.month
from
(
select
*
from
test e
order by
e.count,e.`month` desc) x,
(
select
@rownum := 0,
@part := null,
@r := 0) rt)z
where z.rank in (1,2)
uselessVisitor
2021-03-29 16:15:21 +08:00
@vegetableChick
```
-- part 为 month 对应用谁分组
-- 注意 order by 的顺序
select z.month,z.count,z.rank
from
(select
x.*,
@rownum := @rownum + 1,
if(@part = x.month,@r := @r + 1,@r := 1) as rank,
@part := x.month
from
(
select
*
from
test e
order by
e.month asc,e.count desc) x,
(
select
@rownum := 0,
@part := null,
@r := 0) rt)z
where z.rank in (1,2)
```
vegetableChick
2021-03-29 16:29:59 +08:00
@beichenhpy nb !但是没太看懂, 求大佬讲一下思路
vegetableChick
2021-03-29 16:30:36 +08:00
@beichenhpy 结果出来了, 但是没懂原理
uselessVisitor
2021-03-29 16:41:35 +08:00
@vegetableChick 就是实现了一遍 over(partition by month)
vegetableChick
2021-03-29 16:48:30 +08:00
@beichenhpy 我怎么老觉得不需要 下面的这个`select`, 看上去上面把这些变量又初始化了。 但是去掉就错了
```
select
@rownum := 0,
@part := null,
@r := 0) rt)z
```
uselessVisitor
2021-03-29 16:49:04 +08:00
@vegetableChick 下面是初始化的。。不要去掉
uselessVisitor
2021-03-29 16:49:58 +08:00
@vegetableChick 看一下 mysql 执行顺序。。from 是先执行的
vegetableChick
2021-03-29 16:56:56 +08:00
@beichenhpy 嗯 感谢,学习一下
more1sec
2021-03-29 17:43:47 +08:00
程序代码处理吧。。。别用子查询
zzz686970
2021-03-31 12:59:16 +08:00
@beichenhpy
我测试了一下,子查询里面应该是小于?而且如果 count 有重复的数字,应该换成<

```
select * from t A where (select count(*) from t B where A.month = B.month and A.cnt < B.cnt) < 2

```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/766096

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX