根据我的研究,这是一个非常常见的问题,通常有一个相当简单的解决方案。我的任务是将几个查询从获取所有结果更改为获取每组前 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;
这里的方法是
关于mysql - 具有多个表连接的每组前 N 个,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5319643/