2011-11-24 78 views
1

我有这个相当长的查询,应该给我讲出货量的一些信息,和它的作品,但它的表演糟透了。加载需要大约4500毫秒。SQL查询非常

SELECT 
    DATE(paid_at) AS day, 
    COUNT(*) as order_count, 
    (
     SELECT COUNT(*) FROM line_items 
     WHERE order_id IN (SELECT id from orders WHERE DATE(paid_at) = day) 
    ) as product_count, 
    (
     SELECT COUNT(*) FROM orders 
     WHERE shipping_method = 'colissimo' 
     AND DATE(paid_at) = day 
     AND state IN ('paid','shipped','completed') 
    ) as orders_co, 
    (
     SELECT COUNT(*) FROM orders 
     WHERE shipping_method = 'colissimo' 
     AND DATE(paid_at) = day 
     AND state IN ('paid','shipped','completed') 
     AND paid_amount < 70 
    ) as co_less_70, 
    (
     SELECT COUNT(*) FROM orders 
     WHERE shipping_method = 'colissimo' 
     AND DATE(paid_at) = day 
     AND state IN ('paid','shipped','completed') 
     AND paid_amount >= 70 
    ) as co_plus_70, 
    (
     SELECT COUNT(*) FROM orders 
     WHERE shipping_method = 'mondial_relais' 
     AND DATE(paid_at) = day 
     AND state IN ('paid','shipped','completed') 
    ) as orders_mr, 
    (
     SELECT COUNT(*) FROM orders 
     WHERE shipping_method = 'mondial_relais' 
     AND DATE(paid_at) = day 
     AND state IN ('paid','shipped','completed') 
     AND paid_amount < 70 
    ) as mr_less_70, 
    (
     SELECT COUNT(*) FROM orders 
     WHERE shipping_method = 'mondial_relais' 
     AND DATE(paid_at) = day 
     AND state IN ('paid','shipped','completed') 
     AND paid_amount >= 70 
    ) as mr_plus_70 
    FROM orders 
    WHERE MONTH(paid_at) = 11 
    AND YEAR(paid_at) = 2011 
    AND state IN ('paid','shipped','completed') 
    GROUP BY day; 

任何想法我可能做错了什么或我可以做得更好?我有类似长度的其他查询不需要太多的时间来加载。我认为这将是比例如,具有每一天单个查询(在我的节目,而不是SQL查询)更快。

+0

请张贴该查询的解释计划。 – Hammerite

回答

2

这是因为你正在使用子查询,你不需要他们。

作为一般规则,在主SELECT子句中有子查询的情况下,该子查询将在主SELECT子句中为每个行查询其中的表一次 - 因此,如果您有7个子查询并且是选择30天的日期范围,您将有效地运行210个单独的子查询(加上您的主要查询)。

(有的查询优化器可以解析子查询到在某些情况下,主查询,但作为一般规则,你不能靠这个。)

在这种情况下,你不需要任何的在orders子查询,因为所有你需要的orders数据包含在主查询 - 因此您可以重写这个:

SELECT 
    DATE(paid_at) AS day, 
    COUNT(*) as order_count, 
    (
     SELECT COUNT(*) FROM line_items 
     WHERE order_id IN (SELECT id from orders WHERE DATE(paid_at) = day) 
    ) as product_count, 
    sum(case when shipping_method = 'colissimo' then 1 end) as orders_co, 
    sum(case when shipping_method = 'colissimo' AND 
        paid_amount < 70 then 1 end) as co_less_70, 
    sum(case when shipping_method = 'colissimo' AND 
        paid_amount >= 70 then 1 end) as co_plus_70, 
    sum(case when shipping_method = 'mondial_relais' then 1 end) as orders_mr, 
    sum(case when shipping_method = 'mondial_relais' AND 
        paid_amount < 70 then 1 end) as mr_less_70, 
    sum(case when shipping_method = 'mondial_relais' AND 
        paid_amount >= 70 then 1 end) as mr_plus_70 
    FROM orders 
    WHERE MONTH(paid_at) = 11 
    AND YEAR(paid_at) = 2011 
    AND state IN ('paid','shipped','completed') 
    GROUP BY day; 
2

在您的查询的问题是,一遍又一遍地扫描相同的表。 ORDER表的所有扫描(在你的情况选择)可以转化为多SUM + CASE或COUNT + CASE为SQL query with count and case statement

+0

+1好摘要。 –