mysql中每个组的前N个Sql问题
请注意,我在从类似下面所示的数据集中查询每个类别的前N名时遇到问题。我在这方面看到了各种各样的线索,但我很难使他们的查询适应我的具体问题mysql中每个组的前N个Sql问题,mysql,sql,database,greatest-n-per-group,Mysql,Sql,Database,Greatest N Per Group,请注意,我在从类似下面所示的数据集中查询每个类别的前N名时遇到问题。我在这方面看到了各种各样的线索,但我很难使他们的查询适应我的具体问题 +----+---------------------------------+-------+ | ID | Prod |Cat Id | +----+---------------------------------+-------+ | 1 | kntrn
+----+---------------------------------+-------+
| ID | Prod |Cat Id |
+----+---------------------------------+-------+
| 1 | kntrn | 1 |
| 2 | kntrn e | 1 |
| 3 | e spl | 1 |
| 4 | spl php | 1 |
| 5 | php cicarredgtal | 1 |
| 6 | cicarredgtal servecounterstrike | 1 |
| 7 | servecounterstrike com | 1 |
| 8 | zlv | 2 |
| 9 | zlv enter | 2 |
| 10 | spl php | 2 |
+----+---------------------------------+-------+
我想根据这条规则进行分组,为每个catid选择前3个产品
请注意,从这个意义上讲,top是所有类别中最高的产品数量
因此,对于上面的示例,spl php对于catID 1来说是最高的,因为它在所有类别中出现两次 这可能不是很漂亮,但我认为它会起作用:
SELECT cat_id, prod, pos FROM (
SELECT cat_id, pos, prod, if(@last_id = cat_id, @cnt := @cnt + 1, (@cnt := 0 || @last_id := cat_id)) cnt
FROM (
SELECT p.cat_id, pseq.cnt pos, pseq.prod
FROM (
SELECT prod, count(*) cnt FROM prods GROUP BY prod ORDER BY cnt DESC
) pseq
INNER JOIN prods p ON p.prod = pseq.prod
ORDER BY cat_id, pseq.cnt DESC
) po
) plist
WHERE cnt <= 3;
Based on the above data, this will return:
+--------+-----------+-----+
| cat_id | prod | pos |
+--------+-----------+-----+
| 1 | spl php | 2 |
| 1 | kntrn | 1 |
| 1 | kntrn e | 1 |
| 2 | spl php | 2 |
| 2 | zlv | 1 |
| 2 | zlv enter | 1 |
+--------+-----------+-----+
MySQL不支持TOP关键字,您需要使用LIMIT和ORDER BY来获得相同的结果。我理解这一点,但我在为这样的问题生成相关子查询时遇到了问题。限制每个组的结果计数是一件复杂的事情。对每个类别进行多个查询比较容易。是否涉及其他表?一个有类别和产品关系的表?它是我在项目中遇到的一个遗留表,没有类别和产品关系表。顺便说一句,我喜欢这些脑力练习,但我建议将解决方案更多地放在代码中,而不是放在单个MySQL查询中。为什么你认为代码比sql更好。我想,这需要多次访问数据库。根据您的服务器使用情况,通常情况下,对数据库进行多次微小的往返比一次长查询要好。在大型数据集上,此查询的运行速度相当慢。此外,它非常特定于MySQL,如果您想要更改,将很难移植。此查询执行笛卡尔乘法排序,并且不会返回每个类别的前3名。嗯。它在您提供的示例数据集上起作用。另外,我看不出它是如何进行笛卡尔乘法的——我唯一一次将表连接到它本身是在prod的一个不同的事件中——我将基于上面的数据包含查询的输出。