我有这个相当长的查询,应该给我一些关于货物的信息,它可以工作,但它的表现非常糟糕。加载大约需要4500毫秒。
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 :(得分:1)
您的查询中的问题是一遍又一遍地扫描同一个表。 ORDER表的所有扫描(在您的情况下选择)可以转换为多个SUM + CASE或COUNT + CASE,如SQL query with count and case statement中所示。
答案 1 :(得分:1)
这是因为您在不需要它们的情况下使用子查询。
作为一般规则,在主SELECT子句中有子查询的情况下,该子查询将在主SELECT子句中的每一行中查询其中的表一次 - 因此,如果您有7个子查询并且正在选择日期范围为30天,您将有效地运行210个单独的子查询(加上您的主查询)。
(某些查询优化器可以在某些情况下将子查询解析为主查询,但作为一般规则,您不能依赖于此。)
在这种情况下,您不需要任何orders
子查询,因为您需要的所有orders
数据都包含在主查询中 - 因此您可以将其重写为:< / p>
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;