Ежемесячная распродажа MySQL за последние 12 месяцев, включая месяцы без распродажи

SELECT DATE_FORMAT(date, "%b") AS month, SUM(total_price) as total
FROM cart
WHERE date <= NOW()
and date >= Date_add(Now(),interval - 12 month)
GROUP BY DATE_FORMAT(date, "%m-%Y")

Этот запрос отображает результат только за существующий месяц. Мне нужны продажи за все 12 месяцев.

Вывод:

"month" "total"  
--------------  
"Jun"   "22"
"Aug"   "30"
"Oct"   "19"
"Nov"   "123"
"Dec"   "410"

Необходимый вывод:

"month" "total"  
--------------
"Jan"   "0"
"Feb"   "0"
"Mar"   "0"
"Apr"   "0"
"May"   "0"
"Jun"   "22"
"Jul"   "0"
"Aug"   "30"
"Sep"   "0"
"Oct"   "19"
"Nov"   "123"
"Dec"   "410"

person Wasim A.    schedule 22.12.2014    source источник
comment
Вам понадобится какая-то вспомогательная таблица дат, чтобы получить месяцы без продаж.   -  person davek    schedule 22.12.2014
comment
мы можем сделать это с помощью SELECT 'Jan' AS MONTH UNION SELECT 'Feb' AS MONTH UNION SELECT 'Mar' AS MONTH UNION SELECT 'Apr' AS MONTH UNION SELECT 'May' AS MONTH UNION SELECT 'Jun' AS MONTH UNION SELECT 'Jul ' AS MONTH UNION SELECT 'Aug' AS MONTH UNION SELECT 'Sep' AS MONTH UNION SELECT 'Oct' AS MONTH UNION SELECT 'Nov' AS MONTH UNION SELECT 'Dec' AS MONTH   -  person Wasim A.    schedule 22.12.2014
comment
почему вы используете разные форматы даты в SELECT и GROUP BY?   -  person vladkras    schedule 22.12.2014
comment
в выборе это то, что мне нужно, и в группе, потому что они сортируются   -  person Wasim A.    schedule 22.12.2014
comment
@Wasim, чтобы отсортировать их, вам нужно использовать ORDER BY, группировка будет работать и с Jun, и с Aug.   -  person vladkras    schedule 22.12.2014
comment
order by отсортирует их в алфавитном порядке, так что август придет в начале   -  person Wasim A.    schedule 22.12.2014
comment
@Wasim, конечно, я имел в виду сортировку по дате, а не по форматированной строке. В любом случае, извините, я не могу воспроизвести вашу проблему: sqlfiddle   -  person vladkras    schedule 22.12.2014
comment
@davek как, пожалуйста, объясните ...   -  person Wasim A.    schedule 22.12.2014


Ответы (3)


Рассмотрим следующую таблицу

mysql> select * from cart ;
+------+------------+-------------+
| id   | date       | total_price |
+------+------------+-------------+
|    1 | 2014-01-01 |          10 |
|    2 | 2014-01-20 |          20 |
|    3 | 2014-02-03 |          30 |
|    4 | 2014-02-28 |          40 |
|    5 | 2014-06-01 |          50 |
|    6 | 2014-06-13 |          24 |
|    7 | 2014-12-12 |          45 |
|    8 | 2014-12-18 |          10 |
+------+------------+-------------+

Теперь, согласно логике, вы оглядываетесь назад на один год, и december появится в результате дважды, т.е. dec 2013 and dec 2014, и если нам нужно иметь отдельный счет для них, мы можем использовать следующую технику создания динамического диапазона дат MySql Single Table, выберите последние 7 дней и включите пустые строки

t1.month,
t1.md,
coalesce(SUM(t1.amount+t2.amount), 0) AS total
from
(
  select DATE_FORMAT(a.Date,"%b") as month,
  DATE_FORMAT(a.Date, "%m-%Y") as md,
  '0' as  amount
  from (
    select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
  ) a
  where a.Date <= NOW() and a.Date >= Date_add(Now(),interval - 12 month)
  group by md
)t1
left join
(
  SELECT DATE_FORMAT(date, "%b") AS month, SUM(total_price) as amount ,DATE_FORMAT(date, "%m-%Y") as md
  FROM cart
  where Date <= NOW() and Date >= Date_add(Now(),interval - 12 month)
  GROUP BY md
)t2
on t2.md = t1.md 
group by t1.md
order by t1.md
;

Выход будет

+-------+---------+-------+
| month | md      | total |
+-------+---------+-------+
| Jan   | 01-2014 |    30 |
| Feb   | 02-2014 |    70 |
| Mar   | 03-2014 |     0 |
| Apr   | 04-2014 |     0 |
| May   | 05-2014 |     0 |
| Jun   | 06-2014 |    74 |
| Jul   | 07-2014 |     0 |
| Aug   | 08-2014 |     0 |
| Sep   | 09-2014 |     0 |
| Oct   | 10-2014 |     0 |
| Nov   | 11-2014 |     0 |
| Dec   | 12-2013 |     0 |
| Dec   | 12-2014 |    55 |
+-------+---------+-------+
13 rows in set (0.00 sec)

И если вас не волнует вышеуказанный случай, т.е. dec 2014 and dec 2013

Затем просто измените group by в динамической части даты как

where a.Date <= NOW() and a.Date >= Date_add(Now(),interval - 12 month)
  group by month

и окончательная группа как group by t1.month

person Abhik Chakraborty    schedule 22.12.2014
comment
Не могли бы вы объяснить ту часть, где вы выполнили перекрестное соединение в подзапросе. Я хочу знать, что вы здесь сделали select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date - person Wasim A.; 23.12.2014
comment
другой вопрос, как вы можете сделать этот порядок запросов за последние 12 месяцев, я пробовал по t2.date, но неправильная сортировка из-за NULL created_on для несуществующего месяца. - person Wasim A.; 23.12.2014
comment
select curdate() - INTERVAL (a.a + (10 * b.a) генерирует динамические даты в зависимости от диапазона, который вы просматриваете. Затем это сделает левое соединение с исходным запросом, поэтому все отсутствующие даты появятся из левой таблицы. Также для заказа используйте данные t1, так как данные t2 могут быть не всегда. - person Abhik Chakraborty; 23.12.2014
comment
нравится это решение :) Я только что добавил ORDER BY y.year ASC, x.month ASC, чтобы получить результат для каждого месяца 2015 года сначала и 2016 года после... - person Meloman; 17.08.2016
comment
Чтобы динамически отображать текущий год и прошлый год, просто замените строку SELECT следующим образом: SELECT YEAR(NOW()) -1 AS `year` UNION ALL SELECT YEAR(NOW())) AS y - person Meloman; 17.08.2016

Спасибо за подсказку @pankaj, вот я решил это с помощью этого запроса...

SELECT 
    SUM(IF(month = 'Jan', total, 0)) AS 'Jan',
    SUM(IF(month = 'Feb', total, 0)) AS 'Feb',
    SUM(IF(month = 'Mar', total, 0)) AS 'Mar',
    SUM(IF(month = 'Apr', total, 0)) AS 'Apr',
    SUM(IF(month = 'May', total, 0)) AS 'May',
    SUM(IF(month = 'Jun', total, 0)) AS 'Jun',
    SUM(IF(month = 'Jul', total, 0)) AS 'Jul',
    SUM(IF(month = 'Aug', total, 0)) AS 'Aug',
    SUM(IF(month = 'Sep', total, 0)) AS 'Sep',
    SUM(IF(month = 'Oct', total, 0)) AS 'Oct',
    SUM(IF(month = 'Nov', total, 0)) AS 'Nov',
    SUM(IF(month = 'Dec', total, 0)) AS 'Dec',
    SUM(total) AS total_yearly
    FROM (
SELECT DATE_FORMAT(date, "%b") AS month, SUM(total_price) as total
FROM cart
WHERE date <= NOW() and date >= Date_add(Now(),interval - 12 month)
GROUP BY DATE_FORMAT(date, "%m-%Y")) as sub
person Wasim A.    schedule 22.12.2014
comment
Тем не менее, это отличный ответ от вашего вопроса. Там вы выбрали столбчатый вывод и правильно, согласно вашему комментарию, определили, что вам нужна вспомогательная таблица. Здесь вы генерируете вывод кортежа, двенадцать месяцев в каждой строке. - person LSerni; 22.12.2014
comment
да, вы правы, я не знаю, как это сделать с вспомогательной таблицей. Не могли бы вы объяснить. Мое решение от хорошего до приемлемого. - person Wasim A.; 22.12.2014
comment
Извините меня пожалуйста? Конечно, ты знаешь. Вы описали, как это сделать в своем комментарии... трюк SELECT ... UNION. Используйте это в подзапросе, и вуаля, вот ваша вспомогательная таблица. На первый взгляд мне также кажется, что @AbhikChakraborty опубликовал полное решение. - person LSerni; 22.12.2014
comment
@lserni я сделал это, но это только выбор января, а не все другие названия месяцев, и мне нужен месяц, отсортированный по дате, например, ноябрь 2014, декабрь 2014, январь 2015, февраль 2015. Эта проблема действительно съедает мой разум, прошло 2 дня. - person Wasim A.; 23.12.2014
comment
Привет, есть ли способ также получить год с месяцем AS «Январь», например, если я выберу диапазон дат между 2016 и 2018 годами? - person Sanjay Kumar; 13.09.2018
comment
Это не дает правильного ответа за текущий месяц. Не могли бы вы проверить? Я использую MAX(total_price), чтобы получить максимальное значение месяца. но возвращает наименьшее значение предыдущего месяца в качестве значения текущего месяца. - person arslion; 08.04.2020

Распродажа за месяц. Используйте счетчик для подсчета данных за месяц.

SELECT DATE_FORMAT(date, "%b") AS month, COUNT(total_price) as total
FROM cart
WHERE date <= NOW()
and date >= Date_add(Now(),interval - 12 month)
GROUP BY DATE_FORMAT(date, "%m-%Y")
person Vipin Gangawane    schedule 25.06.2021