Мы могли бы сделать один проход через таблицу, чтобы получить все три агрегата для всех пользователей:
SELECT s.user
, SUM(s.total) AS `ltd_sales`
, SUM(s.total <> 0) AS `cnt_prior_sales`
, SUM(s.total = 0) AS `cnt_giveaways`
FROM orders s
WHERE s.status = 'shipped'
GROUP
BY s.user
Это будет дорого на больших сетах. Но если нам это нужно для всех заказов, для всех пользователей, это, скорее всего, будет быстрее, чем выполнение отдельных коррелированных подзапросов.
Индекс с начальным столбцом user
позволит MySQL использовать индекс для операции GROUP BY
. Включение в индекс столбцов status
и total
позволит полностью удовлетворить запрос из индекса. (С предикатом равенства в столбце status
мы также можем попробовать индекс с status
в качестве ведущего столбца, затем столбец user
, а затем total
.
Если нам нужен этот результат только для небольшой группы пользователей, например мы выбираем только первые 10 строк из первого запроса, затем выполнение отдельного запроса, скорее всего, будет быстрее. Мы просто включили бы условие WHERE s.user = :user
в запрос, как в исходном коде. Но запустите только один запрос, а не три отдельных запроса.
Мы можем объединить это с первым запросом, превратив его во встроенное представление, обернув его в скобки и поместив в предложение FROM
в качестве источника строки
SELECT o.*
, t.ltd_sales
, t.cnt_prior_sale
, t.cnt_giveaways
FROM orders o
JOIN (
SELECT s.user
, SUM(s.total) AS `ltd_sales`
, SUM(s.total <> 0) AS `cnt_prior_sales`
, SUM(s.total = 0) AS `cnt_giveaways`
FROM orders s
WHERE s.status = 'shipped'
GROUP
BY s.user
) t
ON t.user = o.user
WHERE o.status = 'shipped'
Я не уверен насчет того столбца, который называется «предыдущие» продажи ... он возвращает все отгруженные заказы, независимо от сравнения каких-либо дат (даты заказа, даты исполнения, даты отгрузки), которые мы обычно связываем с Понятие о том, что означает «предыдущий».
FOLLOWUP
замечая, что вопрос изменен, удаляя условие "status = 'shipped'
" из подсчета всех заказов пользователем ...
Замечу, что мы можем переместить условия из предложения WHERE
в условные агрегаты.
Не то чтобы все эти результаты нужны ОП, а как демонстрация ...
SELECT s.user
, SUM(IF(s.status='shipped',s.total,0)) AS `ltd_sales_shipped`
, SUM(IF(s.status<>'shipped',s.total,0)) AS `ltd_sales_not_shipped`
, SUM(s.status='shipped' AND s.total <> 0) AS `cnt_shipped_orders`
, SUM(s.status='canceled') AS `cnt_canceled`
, SUM(s.status='shipped' AND s.total = 0) AS `cnt_shipped_giveaways`
FROM orders s
GROUP
BY s.user