MySQL: показывать ежемесячные продажи и включать месяцы, когда продажи не производились
Мне нужна настоящая профессиональная помощь DBA! Я не могу найти разумного решения, используя LEFT JOIN, UNION, UNION ALL или IFNULL(salesblah, 0) в таблице дат относительно таблицы данных о продажах. Запросы запросов в отношении данных о продажах не выполняются, поскольку у торгового представителя могут быть пробелы. Конечно, я мог бы создать в PHP массив для суммирования данных по дате, но должно быть элегантное решение, которого я не вижу, и этот личный вызов утомил меня. Для этого должно быть короткое и приятное решение.
С MySQL 5.5.15 на сервере выдержка из данных о продажах (в настоящее время 800 000 строк и растет ежедневно) выглядит так:
Rep Date QtyOrdered PriceEach
--------------------------------------------------
1 2011-06-05 4 1457.23
1 2011-08-01 1 3342.54
1 2011-08-11 12 112.23
2 2011-05-02 3 2654.23
2 2011-08-23 22 423.43
. ... ... ...
Другая таблица - это просто столбец дат с 2000-01-01 по 2034-12-31
Используя (или не используя) таблицу дат, когда я вызываю респ 1 в запросе, как я могу получить этот результат:
YYYY-MM Total Sales
------------------------
2010-08 0
2010-09 0
2010-10 0
2010-11 0
2010-12 0
2011-01 0
2011-02 0
2011-03 0
2011-04 0
2011-05 0
2011-06 5828.92
2011-07 0
2011-08 4960.14
Я действительно надеюсь убрать неиссякаемую книгу невежливых слов. Спасибо за ваш талант.
РЕДАКТИРОВАТЬ: Решение левого соединения от Дерека пропускает ненулевые месяцы. Метод подзапроса Nerf суммирует все в один месяц. Я считаю, что GROUP BY убивает ненулевые месяцы.
Спасибо! Я полагаю, что самый простой способ - запустить PHP через массив. В конечном счете, это заключается в том, чтобы построить диаграмму за несколько месяцев с помощью GD, и гибридное решение может сохранить шаг в этой части.
Еще раз спасибо!
3 ответа
У меня возникла та же проблема, и я получил решение без использования JOIN или каких-либо сложных вещей. Нужно избегать группирования по общему количеству. При этом отобразятся все заказанные продажи по годам, месяцам и дням, включая дни, когда продаж вообще не было (dayTotal будет равен 0).
SELECT Year(transactions.paymentdate) AS orderYear,Month(transactions.paymentdate) AS orderMonth, Day(transactions.paymentdate) AS orderDay,
SUM(transactions.amount) AS dayTotal
FROM transactions
group by orderYear desc,orderMonth desc, orderDay desc
SELECT CONCAT_WS("-", YEAR(date), DATE_FORMAT(date, '%m') ) AS "YYYY-MM", SUM(Total_Sales) AS "Total Sales"
FROM(
SELECT dt.date, SUM(QtyOrdered * PriceEach) AS Total_Sales
FROM sales_data sd
LEFT JOIN datetbl dt
ON sd.Date = dt.date
WHERE sd.rep = 1 AND dt.date BETWEEN '2011-08-01' AND '2011-08-31'
GROUP BY dt.date
) AS derived_table
Это должно быть довольно близко. Не проверено, но логика должна быть правильной.
select
cast(year(dt.date) as varchar(4)) + '-' + cast(month(dt.date) as varchar(2)),
sum(QtyOrdered * PriceEach)
from salesdata sd
right join datetbl dt
on sd.date = dt.date
where sd.rep = 1 and dt.date between '8/1/2010' and '8/31/2011'
group by cast(year(dt.date) as varchar(4)) + '-' + cast(month(dt.date) as varchar(2))