【发布时间】:2020-11-27 12:17:47
【问题描述】:
我有以下 MySQL 查询,它计算给定日期范围内每个月的订单总数,例如一年。查询可以正常工作,但性能很慢(大约 250 毫秒)。
关于如何重写它以提高效率的任何想法?
WITH recursive `dates` AS (
(
SELECT '2019-11-28' AS item
)
UNION
ALL (
SELECT
item + INTERVAL 1 DAY
FROM
`dates`
WHERE
item + INTERVAL 1 DAY <= '2020-11-27'
)
)
SELECT
DATE_FORMAT(`item`, '%b %y') AS `date`,
COUNT(`orders`.`id`) AS `total`
FROM
`dates`
LEFT JOIN (
SELECT
`orders`.`id`,
`orders`.`created_at`
FROM
`orders`
INNER JOIN `locations` ON `orders`.`location_id` = `locations`.`id`
WHERE
`orders`.`shop_id` = 10379184
AND `locations`.`country_id` = 128
AND `orders`.`created_at` >= '2019-11-28 12:01:42'
AND `orders`.`created_at` <= '2020-11-27 12:01:42'
) AS `orders` ON DATE(`orders`.`created_at`) = `dates`.`item`
GROUP BY
`date`
更新:有些人建议使用两个左连接,但是如果我这样做,则不会应用 country_id 过滤器:
WITH recursive `dates` AS (
(
SELECT
'2019-11-28' AS item
)
UNION
ALL (
SELECT
item + INTERVAL 1 DAY
FROM
`dates`
WHERE
item + INTERVAL 1 DAY <= '2020-11-27'
)
)
SELECT
DATE_FORMAT(`item`, '%b %y') AS `date`,
COUNT(`orders`.`id`) AS `total`
FROM
`dates`
LEFT JOIN `orders` USE INDEX (`orders_created_at_index`) ON DATE(`created_at`) = `dates`.`item`
AND `orders`.`shop_id` = 10379184
AND `orders`.`created_at` >= '2019-11-28 12:22:43'
AND `orders`.`created_at` <= '2020-11-27 12:22:43'
LEFT JOIN `locations` ON `orders`.`location_id` = `locations`.`id`
AND `locations`.`country_id` = 128
GROUP BY
`date`
谢谢!
【问题讨论】:
-
(LEFT JOIN) 子查询的目的是什么?你不能简单地 LEFT JOIN 只是 order 表吗?
-
限定列名,以便清楚列的来源。
-
为什么不简单地
... FROM dates LEFT JOIN orders LEFT JOIN locations ...?使用子查询的原因是什么? -
子查询的原因是如果我使用两个左连接,那么 country_id 不会被应用,例如
sql LEFT JOIN `orders` USE INDEX (`orders_created_at_index`) ON DATE(`created_at`) = `dates`.`item` AND `orders`.`shop_id` = 10379184 AND `orders`.`created_at` >= '2019-11-28 12:22:43' AND `orders`.`created_at` <= '2020-11-27 12:22:43' LEFT JOIN `locations` ON `orders`.`location_id` = `locations`.`id` AND `locations`.`country_id` = 128 -
需要左连接来保留生成的
WITH RECURSIVE日期。