【问题标题】:MySQL monthly Sale of last 12 months including months with no SaleMySQL 过去 12 个月的月度销售,包括没有销售的月份
【发布时间】:2015-02-20 10:40:09
【问题描述】:
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"

【问题讨论】:

  • 您将需要某种辅助日期表来获取没有销售的月份。
  • 我们可以通过 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
  • 为什么SELECTGROUP BY 使用不同的日期格式?
  • 在选择中这是我需要的,并在分组中,因为要保持它们的排序
  • @Wasim 让它们保持排序你需要使用ORDER BY,分组也可以在JunAug 上工作

标签: mysql sql zero monthcalendar not-exists


【解决方案1】:

感谢@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

【讨论】:

  • 然而,这是与您的问题的不同答案。在那里,您选择了一个列输出,并且根据您的评论正确地确定您需要一个辅助表。在这里,您正在生成一个元组输出,每行十二个月。
  • 是的,你是对的,我不知道如何使用辅助表来做到这一点。你能解释一下吗。我的解决方案可以接受。
  • 对不起?你当然知道。 在您的评论中描述了如何做到这一点...SELECT ... UNION 技巧。在子选择中使用它,然后,你的辅助表就出来了。乍一看,@AbhikChakraborty 在我看来也发布了完整的解决方案。
  • @lserni 我做到了,但它只选择一月,而不是所有其他月份的名称,我需要按日期排序的月份,如 nov2014、dec2014、jan2015、feb2015。这个问题实在是太费脑子了,2天过去了
  • 嗨,有没有什么办法也可以得到月份为“一月”的年份,比如我选择 2016 年到 2018 年之间的日期范围
【解决方案2】:

考虑下表

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, Select last 7 days and include empty rows

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

【讨论】:

  • 你能解释一下你在子查询中交叉连接的部分吗?我想知道你在这里做了什么选择 curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
  • 另一个问题,如何在过去 12 个月之前进行此查询排序,我在 t2.date 之前尝试过,但由于 NULL created_on 不存在月份而导致排序不正确..
  • select curdate() - INTERVAL (a.a + (10 * b.a) 正在根据您查看的范围生成动态日期。然后这将对原始查询进行左连接,因此所有缺失的日期都将出现在左表中。也用于订购使用 t1 数据,因为 t2 数据可能并不总是存在。
  • 喜欢这个解决方案 :) 我刚刚添加了ORDER BY y.year ASC, x.month ASC 以得到 2015 年第一个月和 2016 年之后每个月的结果...
  • 要动态获取当前年份和去年,只需将 SELECT 行替换为:SELECT YEAR(NOW()) -1 AS `year` UNION ALL SELECT YEAR(NOW())) AS y
【解决方案3】:

每月销售 使用 Count 统计月份数据。

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")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多