mysql - 具有多个表连接的每个组的前 N ​​个

标签 mysql sql group-by greatest-n-per-group

根据我的研究,这是一个非常普遍的问题,通常有一个相当简单的解决方案。我的任务是将几个查询从获取所有结果更改为获取每个组的前 3 个。起初一切进展顺利,我使用了该网站的一些建议和答案来实现这一目标(查看最多的产品)。但是,由于多个连接,我在使用最后一个“畅销产品”时遇到了困难。

基本上,我需要按每个产品的最高销售额排序所有产品,其中每个供应商的最大产品数为 3 我已经连接了多个表以创建原始查询,并且每次我尝试使用变量生成排名时,它都会产生无效结果。以下内容应该有助于更好地理解问题(为简洁起见,我删除了不必要的字段):

产品表

productid | vendorid | approved | active | deleted

供应商表

vendorid | approved | active | deleted

订单表

orderid | `status` | deleted

订单项目表

orderitemid | orderid | productid | price

现在,我获取所有结果的原始查询如下:

SELECT COUNT(oi.price) AS `NumSales`, 
       p.productid, 
       p.vendorid
FROM products p
INNER JOIN vendors v ON (p.vendorid = v.vendorid)
INNER JOIN orders_items oi ON (p.productid = oi.productid)
INNER JOIN orders o ON (oi.orderid = o.orderid)
WHERE (p.Approved = 1 AND p.Active = 1 AND p.Deleted = 0)
AND (v.Approved = 1 AND v.Active = 1 AND v.Deleted = 0)
AND o.`Status` = 'SETTLED'
AND o.Deleted = 0
GROUP BY oi.productid
ORDER BY COUNT(oi.price) DESC
LIMIT 100;

最后,(这就是我被难住的地方),我试图改变上述声明,以便我只收到每个供应商的前 3 名产品(按 # 售出)。我会添加到目前为止的内容,但我很尴尬,而且这个问题已经是一堵文字墙了。我试过变量,但一直得到无效结果。任何帮助将不胜感激。

最佳答案

即使您指定了 LIMIT 100,这种类型的查询也需要进行全面扫描和构建表格,然后检查每条记录并为行编号,最后筛选出您要显示的 100 个。

select
    vendorid, productid, NumSales
from
(
    select
        vendorid, productid, NumSales,
        @r := IF(@g=vendorid,@r+1,1) RowNum,
        @g := vendorid
    from (select @g:=null) initvars
    CROSS JOIN 
    (
        SELECT COUNT(oi.price) AS NumSales, 
               p.productid, 
               p.vendorid
        FROM products p
        INNER JOIN vendors v ON (p.vendorid = v.vendorid)
        INNER JOIN orders_items oi ON (p.productid = oi.productid)
        INNER JOIN orders o ON (oi.orderid = o.orderid)
        WHERE (p.Approved = 1 AND p.Active = 1 AND p.Deleted = 0)
        AND (v.Approved = 1 AND v.Active = 1 AND v.Deleted = 0)
        AND o.`Status` = 'SETTLED'
        AND o.Deleted = 0
        GROUP BY p.vendorid, p.productid
        ORDER BY p.vendorid, NumSales DESC
    ) T
) U
WHERE RowNum <= 3
ORDER BY NumSales DESC
LIMIT 100;

这里的做法是

  1. Group by 得到 NumSales
  2. 使用变量对每个供应商/产品的销售额进行行编号
  3. 过滤编号数据集以允许每个供应商最多 3 个
  4. 按 NumSales DESC 订购剩余的,只返回 100

关于mysql - 具有多个表连接的每个组的前 N ​​个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5319643/

相关文章:

python - 插入 MySQL 失败并出现错误

生产环境MySql慢查询日志

java - 如何对多对多关系执行存在查询

SQL 查询选择具有不同主题的最新记录

mysql - 选择具有最大值的行数

mysql - 减少 MySQL 字段中的字符

php - nginx 和 php5-fpm 对 Laravel 应用程序的响应非常慢

c# - 将数据表传递给存储过程

SQL:查找在某个类别中没有支出的客户

apache-spark - 我应该避免在数据集/数据帧中使用 groupby() 吗?