【问题标题】:MySQL Get products also bought with a product / Optimise IN queryMySQL Get 产品还买了一个产品 / 优化 IN 查询
【发布时间】:2016-08-19 09:29:24
【问题描述】:

我正在尝试写一个简单的“购买此产品的客户也购买了...”

我有一个包含订单的order 表和一个包含与订单相关的所有产品的order_product 表。

为了找出使用product_id = 155 购买的五个最受欢迎的产品,我编写了以下查询:

select product_id, count(*) as cnt 
from order_product 
where product_id != 155 
and order_id in 
(select order_id from order_product where product_id = 155) 
group by product_id 
order by cnt desc 
limit 5;

因此,内部查询获取包含我感兴趣的产品的所有订单的列表 (product_id = 155),然后外部查询查找不是同一产品但属于我的产品所在的顺序。

然后将它们排序并限制在前 5 名。

我认为这行得通,但它需要很长时间 - 我想这是因为我正在使用包含几千个列表的 IN。

我想知道是否有人可以指出我以更优化的方式编写它的方向。

非常感谢任何帮助。

【问题讨论】:

  • 您是否曾经两次在“订单”中拥有相同的product_id?如果是这样,答案必须更加努力。
  • 好点,但不是 - 如果将同一 id 的产品添加到订单中,则应增加 qty 字段而不是添加另一条记录。

标签: mysql sql opencart query-optimization


【解决方案1】:

您可以尝试更改此设置:

select p1.product_id, p1.count(*) as cnt

select p1.product_id, count(distinct p1.order_id) as cnt 

看看这是否会给你带来不同的结果

编辑: 来自cmets

如果您更喜欢在第一个查询中生成结果,您可以尝试使用这个:

select a.product_id, count(*) as cnt 
from order_product a
join (select distinct order_id from order_product where product_id = 155) b on (a.order_id = b.order_id)
where a.product_id != 155 
group by a.product_id 
order by cnt desc 
limit 5;

对现有查询的小改动 :)

【讨论】:

  • 是的,这确实给出了不同的结果。事实上,这三个都是不同的,
  • 通过进行一些测试,似乎在您的情况下,count(*) 给出了在产品 155 旁边订购了多少给定 product_id。而 count(distinct p1.order_id) 为您提供给定 product_id 在产品 155 旁边的订单数。是否有意义?
  • 是的,我认为这确实有道理,但是,我希望其中一个(我认为是第一个)给出与我原来的查询相同的结果,但两者都没有!?
  • 我之前的陈述可能有点错误。根据我的理解,经过更多研究。您的第一个查询:计算与 155 关联的所有产品,无论其是否相同(例如,产品 111 在 155 旁边的订单 1 中订购了 3 次,您的查询将其计为 3)。 count(*) 获取与 155 关联的所有产品以及由连接引起的任何重复,count(distinct order_id) 计算该产品在 155 中的唯一订单数。
  • 如果查询仍然需要很长时间,请告诉我 :)
【解决方案2】:

您可以尝试加入而不是子选择。比如:

select p1.product_id, p1.count(*) as cnt 
from order_product p1 JOIN order_product p2 on p1.order_id = p2. order_id
where p1.product_id != 155 
and p2.product_id = 155
group by p1.product_id 
order by p1.cnt desc 
limit 5;

【讨论】:

  • 使用不带前缀的 count(*) 有效,但与我的原始查询给出不同的结果
  • 手动检查这两个查询——哪一个的计数正确?
  • 如果您想要产品“namex”,请执行SELECT name FROM ( Diego's query ) AS x JOIN products USING(product_id)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多