Вычислить общую сумму в MySQL
у меня есть этот запрос MySQL:
SELECT DAYOFYEAR(`date`) AS d, COUNT(*)
FROM `orders`
WHERE `hasPaid` > 0
GROUP BY d
ORDER BY d
который возвращает что-то вроде этого:
d | COUNT(*) |
20 | 5 |
21 | 7 |
22 | 12 |
23 | 4 |
то, что я действительно хотел бы, это еще один столбец в конце, чтобы показать общую сумму:
d | COUNT(*) | ??? |
20 | 5 | 5 |
21 | 7 | 12 |
22 | 12 | 24 |
23 | 4 | 28 |
это возможно?
7 ответов:
возможно, более простое решение для вас и предотвращает базу данных, чтобы сделать тонну запросов. Это выполняет только один запрос, а затем делает небольшую математику на результаты в один проход.
SET @runtot:=0; SELECT q1.d, q1.c, (@runtot := @runtot + q1.c) AS rt FROM (SELECT DAYOFYEAR(`date`) AS d, COUNT(*) AS c FROM `orders` WHERE `hasPaid` > 0 GROUP BY d ORDER BY d) AS q1
Это даст вам дополнительный столбец RT (running total). Не пропустите оператор SET вверху, чтобы сначала инициализировать текущую общую переменную, или вы просто получите столбец нулевых значений.
SELECT DAYOFYEAR(O.`date`) AS d, COUNT(*), (select count(*) from `orders` where DAYOFYEAR(`date`) <= d and `hasPaid` > 0) FROM `orders` as O WHERE O.`hasPaid` > 0 GROUP BY d ORDER BY d
для этого потребуется некоторая синтаксическая настройка (у меня нет MySQL для ее тестирования), но она показывает вам идею. Подзапрос просто должен вернуться и добавить все новое, что вы уже включили во внешний запрос, и он должен сделать это для каждой строки.
посмотри этот вопрос для того, как использовать соединения для достижения того же.
для решения проблем, связанных с ухудшением производительности с ростом данных: так как есть макс. 366 дней год, и я предполагаю, что вы не выполняете этот запрос против нескольких лет, подзапрос будет оцениваться до 366 раз. С соответствующими индексами на дату и флаг hasPaid, вы будете в порядке.
Я бы сказал, что это невозможно каждая итоговая строка должна быть независимой. Использовать язык программирования для получения этих значений
Если у вас нет другого варианта, кроме как делать это в sql, я бы суммировал результаты на языке программирования, который делает запрос. Места гнездования, как это стало очень медленно, так как таблица растет.
начиная с MySQL 8, вы будете использовать окне функции для такого рода запрос:
SELECT dayofyear(`date`) AS d, count(*), sum(count(*)) OVER (ORDER BY dayofyear(`date`)) FROM `orders` WHERE `hasPaid` > 0 GROUP BY d ORDER BY d
В приведенном выше запросе агрегатные функции
count(*)
вложен внутри функции окнаsum(..) OVER (..)
, что возможно из-за логический порядок операций в SQL. Если это слишком запутанно, вы можете легко прибегнуть к использованию производной таблицы илиWITH
п. чтобы лучше структурировать ваш запрос:WITH daily (d, c) AS ( SELECT dayofyear(`date`) AS d, count(*) FROM `orders` WHERE `hasPaid` > 0 GROUP BY d ) SELECT d, c, sum(c) OVER (ORDER BY d) ORDER BY d