使用OR通过几个联接优化左联接?

时间:2019-01-30 13:48:55

标签: mysql optimization left-join

这是我的查询(已编辑)

SELECT
  en.name AS name,
  en.entity_id,
  COUNT(o.order_id) AS orders_qty,
  ROUND(SUM(o.total)) AS orders_sum,
  ROUND((SUM(o.total) / COUNT(o.order_id))) AS average_purchase,
  MIN(o.date_added) AS first_purchase,
  MAX(o.date_added) AS last_purchase,
  (SELECT COUNT(*) FROM oc_order WHERE order_status_id <> 0 AND customer_id = c.customer_id AND date_added <= NOW() - INTERVAL 3 MONTH) as periodicity
FROM oc_xile_entity en
  LEFT JOIN oc_xile_customer_to_entity c2en ON (c2en.entity_id = en.entity_id)
  LEFT JOIN oc_customer c ON (c2en.customer_id = c.customer_id)
LEFT JOIN oc_order o FORCE INDEX FOR JOIN (`unreg_customer_id`) ON ((o.customer_id = c2en.customer_id OR o.unreg_customer_id = c2en.customer_id) AND order_status_id <> 0)
  WHERE en.entity_id IS NOT NULL
GROUP BY en.entity_id
ORDER BY name ASC
LIMIT 0,700

...以及表格的相关部分...

CREATE TABLE oc_order 
( order_id int(11) NOT NULL PRIMARY KEY 
, customer_id int(11) NOT NULL DEFAULT '0'
, unreg_customer_id (unreg_customer_id)
, unreg_customer_id int(11) NOT NULL
, order_status_id int(11) NOT NULL DEFAULT '0'
, INDEX (customer_id)
);

CREATE TABLE oc_customer 
(customer_id int(11) NOT NULL PRIMARY KEY);

CREATE TABLE oc_xile_customer_to_entity 
(entity_id int(11) NOT NULL
,customer_id int(11) NOT NULL
,PRIMARY KEY (entity_id,customer_id)
,INDEX entity_id
);

当我进行查询时,按表顺序35506行要花费超过15秒的时间

最繁重的查询

LEFT JOIN oc_order o ON ((o.customer_id = c2en.customer_id OR o.unreg_customer_id = c2en.customer_id) AND order_status_id  0)

优化它的最佳方法是像这样FORCE INDEX FOR JOIN (unreg_customer_id)添加LEFT JOIN oc_order o FORCE INDEX FOR JOIN (unreg_customer_id) ON ((o.customer_id = c2en.customer_id OR o.unreg_customer_id = c2en.customer_id) AND order_status_id <> 0) 它的增加速度和查询时间已变为3秒。但我认为它可以优化得更好。有谁能够帮助我? 查询说明 explain

1 个答案:

答案 0 :(得分:0)

Du?该查询对jQuery(document).ready(()=>{ let placeOrder = document.getElementById('place_order'); window.dataLayer = window.dataLayer || []; placeOrder.addEventListener("mouseover", (e)=>{ alert('hover'); }); });// end of document ready 不执行任何操作。但是,优化器可能太笨了,无法丢弃它们并获得等效的查询:

LEFT JOINs

那么您可能选择了SELECT en.name AS name , en.entity_id FROM oc_xile_entity en WHERE en.entity_id IS NOT NULL GROUP BY en.entity_id ORDER BY name ASC LIMIT 0 , 700 而不是按其分组,这可能是“不合适的”。如果有多个name与一个names相关联,那么应该显示哪个 entity_id

请描述您要达到的目标,并提供name