在mysql中按月分组,即使数据不存在
假设我有一张销售表,如下所示在mysql中按月分组,即使数据不存在,mysql,Mysql,假设我有一张销售表,如下所示 Customer Date Amount Paul 15/01/2015 2000 Jonathan 15/01/2015 3000 Taylor 15/01/2015 2000 Mark 15/01/2015 3000 Paul 15/02/2015 2000 Jonathan 15/02/2015 3000 Paul 25/02/2015 4000 Jonathan 25/02/2015 5
Customer Date Amount
Paul 15/01/2015 2000
Jonathan 15/01/2015 3000
Taylor 15/01/2015 2000
Mark 15/01/2015 3000
Paul 15/02/2015 2000
Jonathan 15/02/2015 3000
Paul 25/02/2015 4000
Jonathan 25/02/2015 5000
Jonathan 15/03/2015 2000
Jonathan 25/04/2015 5000
Taylor 25/04/2015 4000
Mark 25/04/2015 5000
Paul 25/05/2015 4000
Jonathan 25/05/2015 5000
Taylor 25/05/2015 4000
Mark 25/05/2015 5000
在报告中,我希望看到如下所示:
Customer Month Amount
Paul 201501 2000
Paul 201502 6000
Paul 201503 0
Paul 201504 0
Paul 201505 4000
请告诉我怎么做
更新
Customer Month Amount
Paul 201501 2000
Paul 201502 6000
Paul 201503 0
Paul 201504 0
Paul 201505 4000
Jonathan 201501 3000
Jonathan 201502 8000
Jonathan 201503 2000
Jonathan 201504 5000
Jonathan 201505 5000
Taylor 201501 2000
Taylor 201502 0
Taylor 201503 0
Taylor 201504 4000
Taylor 201505 4000
Mark 201501 3000
Mark 201502 0
Mark 201503 0
Mark 201504 5000
Mark 201505 5000
我还需要为所有客户创建此视图。请告诉我怎么做。您可以构建一个包含所有月份的在线表格,然后在上面加入您的销售表格 大概是这样的:
SELECT s.customer_name as Customer,
CONCAT(months.m, '-', years.y) as Month,
s.amount as Amount
FROM (
SELECT '01' AS m UNION ALL SELECT '02' UNION ALL SELECT '03' UNION ALL
SELECT '04' UNION ALL SELECT '05' UNION ALL SELECT '06' UNION ALL
SELECT '07' UNION ALL SELECT '08' UNION ALL SELECT '09' UNION ALL
SELECT '10' UNION ALL SELECT '11' UNION ALL SELECT '12') AS months
CROSS JOIN (
SELECT '2015' AS y UNION ALL SELECT '2016') AS years
LEFT JOIN sales_table AS s
ON DATE_FORMAT(s.date, '%Y-%c') = CONCAT(years.y, '-', months.m)
GROUP BY CONCAT(months.m, '-', years.y)
这是一个解决方案,带有一个演示,使用您提供的日期。此外,还为模拟添加了更多数据 下降表销售 SQL: 输出:
mysql> select * from sales;
+----------+------------+--------+
| Customer | Date | Amount |
+----------+------------+--------+
| Paul | 2015-01-15 | 2000 |
| Jonathan | 2015-01-15 | 3000 |
| Taylor | 2015-01-15 | 2000 |
| Mark | 2015-01-15 | 3000 |
| Paul | 2015-02-15 | 2000 |
| Jonathan | 2015-02-15 | 3000 |
| Paul | 2015-02-25 | 4000 |
| Jonathan | 2015-02-25 | 5000 |
| Jonathan | 2015-03-15 | 2000 |
| Jonathan | 2015-04-15 | 5000 |
| Taylor | 2015-04-25 | 4000 |
| Mark | 2015-04-25 | 5000 |
| Paul | 2015-05-25 | 4000 |
| Jonathan | 2015-05-25 | 5000 |
| Taylor | 2015-05-25 | 4000 |
| Mark | 2015-05-25 | 5000 |
+----------+------------+--------+
16 rows in set (0.00 sec)
mysql>
mysql> -- query wanted
mysql> select
-> COALESCE(s.Customer, '') AS Customer, DATE_FORMAT(m2.cont_date, '%Y%m') AS Month, SUM(COALESCE(s.Amount, 0)) AS Amount
-> from (
-> select (select MAX(`Date`) from sales) - interval (year.b * 10 + month.a) MONTH AS cont_date
-> from (
-> select 0 b union select 1 union select 2 union select 3 union select 4 union
-> select 5 union select 6 union select 7 union select 8 union select 9) AS year
-> CROSS JOIN
-> (
-> select 0 a union select 1 union select 2 union select 3 union select 4 union
-> select 5 union select 6 union select 7 union select 8 union select 9) AS month
-> where (year.b * 10 + month.a) < (select timestampdiff(month, MIN(`Date`), MAX(`Date`)) + 1 from sales) ) m2
-> LEFT JOIN sales s ON s.Customer = 'paul' AND DATE_FORMAT(m2.cont_date, '%Y%m') = DATE_FORMAT(s.`Date`, '%Y%m')
-> GROUP BY Month;
+----------+--------+--------+
| Customer | Month | Amount |
+----------+--------+--------+
| Paul | 201501 | 2000 |
| Paul | 201502 | 6000 |
| | 201503 | 0 |
| | 201504 | 0 |
| Paul | 201505 | 4000 |
+----------+--------+--------+
5 rows in set (0.00 sec)
通过queryHi Dylan发布您的群组,谢谢您的回答。当我按客户分组时,因为我的表和月份中有50多个客户,所以应该出现的0不会出现。在您给定的示例中,显示的是201501之后的201410。请让我知道用什么涂抹日期格式。选择日期(格式为“2015-01-15”,“%Y%m”;它返回'201501',我想说的是-根据我们的要求,当金额列中没有一个月的条目时,它应该显示0。但事实上,它没有显示任何价值,也没有跳过这个月。在您给出的示例中,它应该在201411和201412的金额列中显示0,但没有显示任何内容。如您所述,我当前显示的是select union的24个月。我想在amount列中显示没有任何数据的月份-就像问题中的month 201503没有任何数据,但它仍然应该显示在报告中。和月栏中的201503相比,金额应该是0I。我刚刚更新了帖子并扩大了它可以处理的范围。现在它可以处理长达8年,大约100个月。请再试一次。
mysql> select * from sales;
+----------+------------+--------+
| Customer | Date | Amount |
+----------+------------+--------+
| Paul | 2015-01-15 | 2000 |
| Jonathan | 2015-01-15 | 3000 |
| Taylor | 2015-01-15 | 2000 |
| Mark | 2015-01-15 | 3000 |
| Paul | 2015-02-15 | 2000 |
| Jonathan | 2015-02-15 | 3000 |
| Paul | 2015-02-25 | 4000 |
| Jonathan | 2015-02-25 | 5000 |
| Jonathan | 2015-03-15 | 2000 |
| Jonathan | 2015-04-15 | 5000 |
| Taylor | 2015-04-25 | 4000 |
| Mark | 2015-04-25 | 5000 |
| Paul | 2015-05-25 | 4000 |
| Jonathan | 2015-05-25 | 5000 |
| Taylor | 2015-05-25 | 4000 |
| Mark | 2015-05-25 | 5000 |
+----------+------------+--------+
16 rows in set (0.00 sec)
mysql>
mysql> -- query wanted
mysql> select
-> COALESCE(s.Customer, '') AS Customer, DATE_FORMAT(m2.cont_date, '%Y%m') AS Month, SUM(COALESCE(s.Amount, 0)) AS Amount
-> from (
-> select (select MAX(`Date`) from sales) - interval (year.b * 10 + month.a) MONTH AS cont_date
-> from (
-> select 0 b union select 1 union select 2 union select 3 union select 4 union
-> select 5 union select 6 union select 7 union select 8 union select 9) AS year
-> CROSS JOIN
-> (
-> select 0 a union select 1 union select 2 union select 3 union select 4 union
-> select 5 union select 6 union select 7 union select 8 union select 9) AS month
-> where (year.b * 10 + month.a) < (select timestampdiff(month, MIN(`Date`), MAX(`Date`)) + 1 from sales) ) m2
-> LEFT JOIN sales s ON s.Customer = 'paul' AND DATE_FORMAT(m2.cont_date, '%Y%m') = DATE_FORMAT(s.`Date`, '%Y%m')
-> GROUP BY Month;
+----------+--------+--------+
| Customer | Month | Amount |
+----------+--------+--------+
| Paul | 201501 | 2000 |
| Paul | 201502 | 6000 |
| | 201503 | 0 |
| | 201504 | 0 |
| Paul | 201505 | 4000 |
+----------+--------+--------+
5 rows in set (0.00 sec)