使用LEFT JOINS优化MySql查询

时间:2016-04-03 23:11:57

标签: mysql left-join query-optimization

我正在尝试获取未订购6个月或更长时间的客户列表。我在查询中使用了4个表

  • 帐户(account_id)
  • stores(store_id,account_id)
  • customers(store_id,customer_id)
  • 订单(order_id,customer_id,store_id)

客户和订单表分别很大,3M和26M行,因此在我的查询中使用左连接会使查询时间过长。我相信我已正确索引我的表

这是我用过的查询

SELECT cus.customer_id, MAX(o.order_date), cus.store_id, s.account_id, store_name
FROM customers cus 
LEFT JOIN stores s ON s.store_id=cus.store_id  
LEFT JOIN orders o ON o.customer_id=cus.customer_id AND o.store_id=cus.store_id
WHERE account_id=26  AND  
    (SELECT order_id 
        FROM orders o 
        WHERE o.customer_id=cus.customer_id 
        AND  o.store_id=cus.store_id 
        AND o.order_date < CURRENT_DATE() - INTERVAL 6 MONTH 
        ORDER BY order_id DESC LIMIT 0,1) IS NOT NULL 
GROUP BY cus.customer_id, cus.client_id;

我需要获取最后一个订单日期,这就是我加入订单表的原因,但是因为客户可以有多个订单,所以它返回了多行客户,这是为什么我使用了group by子句。

如果有人可以帮助我查询。

2 个答案:

答案 0 :(得分:2)

从这开始:

SELECT  customer_id, MAX(order_date) AS last_order_date
    FROM  orders
    GROUP BY  customer_id
    HAVING  last_order_date < NOW() - INTERVAL 6 MONTH;

假设为您提供了相关的customer_id,请转到

SELECT ...
    FROM ( that-select-as-a-subquery ) AS old
    JOIN other-tables-as-needed  ON USING(customer_id)

如有必要,JOIN返回订单以获取更多信息。 尝试获取该子查询中的其他列。 (那是&#34; groupwise max&#34;问题。)

答案 1 :(得分:0)

您在orders表上使用有序且有限的子查询的策略可能是您表现不佳的原因。

此子查询将生成一个虚拟表,显示每个不同客户的最新订单的日期。 (我猜一个独特的客户是由customer_id, store_id对区分的。

                 SELECT MAX(order_date) recent_order_date,
                        customer_id, store_id
                   FROM orders
                  GROUP BY customer_id, store_id

然后,您可以在查询中使用该子查询,就好像它是一个表

SELECT cus.customer_id, summary.recent_order_date, 
       cus.store_id, s.account_id, store_name
  FROM customers cus 
  JOIN stores s ON s.store_id=cus.store_id 
  JOIN (
              SELECT MAX(order_date) recent_order_date,
                     customer_id, store_id
                FROM orders
               GROUP BY customer_id, store_id
       ) summary  ON summary.customer_id = cus.customer_id
                 AND summary.store_id = s.store_id
 WHERE summary.recent_order_date < CURRENT_DATE - INTERVAL 6 MONTH
   AND store.account_id = 26

此方法将GROUP BY移动到内部查询,并消除了浪费的ORDER BY ... LIMIT查询模式。不必为外部查询中的每一行重新创建内部查询。

我不明白您在查询中使用LEFT JOIN操作的原因。

顺便说一句,大多数人,当他们不熟悉SQL时,对于哪些索引有用而哪些索引不是很有直觉。因此,在寻求帮助时,显示索引总是好的。在此期间,请阅读:

http://use-the-index-luke.com/