【问题标题】:Mysql sales table grouped by customer and displayed by month columns pivot queryMysql 销售表按客户分组并按月列显示透视查询
【发布时间】:2015-02-26 03:35:57
【问题描述】:

我有一个 sales 表,其中包含以下列:

|  Customer_Id | amount |  date  |

customer_id 对数据进行分组并在不同的月份列上显示每个 Customer_id(每个 Customer_id 一行)的每月总金额 (SUM) 的最佳方法是什么?

所需的输出类似于:

Customer     |January    | February   | March       | ....

Customer_id  |SUM amount | SUM amount | SUM amount | ....

我相信在 Sql 中这称为数据透视表。

¡谢谢!

【问题讨论】:

  • 你有什么尝试吗?
  • 这通常通过分组来完成,就像在大多数答案中一样,然后是使用case 表达式的列。 sum(case when month(date) = 1 then amount else null end) as January, ...
  • 一般来说,出于可扩展性和灵活性的原因,如果有这样的东西可用,最好在应用程序级代码(例如 PHP)中处理数据显示问题。
  • @shawnt00 我如何使用 sum(case when mont... 并且结果每个 customer_id 只显示一行?
  • 您可能没有添加 GROUP BY Customer_id,根据定义,每个 customer_id 都会为您提供一行。

标签: mysql database pivot-table


【解决方案1】:

假设您有下表:

mysql> select * from sales;
+-------------+--------+------------+
| customer_id | amount | date       |
+-------------+--------+------------+
|           1 |     12 | 2015-01-01 |
|           1 |      1 | 2015-01-02 |
|           1 |    663 | 2015-02-12 |
|           2 |     22 | 2015-01-03 |
|           2 |     21 | 2015-02-12 |
|           2 |     11 | 2015-02-12 |
|           2 |      9 | 2015-04-12 |
+-------------+--------+------------+

您可以使用以下查询来做到这一点:

SELECT
  customer_id,
  sum(if(month(date) = 1, amount, 0))  AS Jan,
  sum(if(month(date) = 2, amount, 0))  AS Feb,
  sum(if(month(date) = 3, amount, 0))  AS Mar,
  sum(if(month(date) = 4, amount, 0))  AS Apr,
  sum(if(month(date) = 5, amount, 0))  AS May,
  sum(if(month(date) = 6, amount, 0))  AS Jun,
  sum(if(month(date) = 7, amount, 0))  AS Jul,
  sum(if(month(date) = 8, amount, 0))  AS Aug,
  sum(if(month(date) = 9, amount, 0))  AS Sep,
  sum(if(month(date) = 10, amount, 0)) AS Oct,
  sum(if(month(date) = 11, amount, 0)) AS Nov,
  sum(if(month(date) = 12, amount, 0)) AS `Dec`
FROM sales
GROUP BY customer_id;

还有输出:

+-------------+------+------+------+------+------+------+------+------+------+------+------+------+
| customer_id | Jan  | Feb  | Mar  | Apr  | May  | Jun  | Jul  | Aug  | Sep  | Oct  | Nov  | Dec  |
+-------------+------+------+------+------+------+------+------+------+------+------+------+------+
|           1 |   13 |  663 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |
|           2 |   22 |   32 |    0 |    9 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |    0 |
+-------------+------+------+------+------+------+------+------+------+------+------+------+------+

【讨论】:

  • 很好的答案!但是我怎么能让每个不同的 customer_id 只显示一行?
  • 去掉month(date)上的分组。我在上面的 cmets 中写的 sum+case 是执行此操作的标准 SQL 方式,但除此之外我认为它们是等价的。
  • @helloworld 我编辑了我的帖子,现在返回正确的数据。
【解决方案2】:

试试这个:

SELECT `Customer_id` AS Customer,
SUM(`amount`) AS MONTHNAME(`date`)
FROM `sales`
GROUP BY YEAR(`date`), MONTH(`date`);

【讨论】:

  • 感谢您的回答。我每个月没有不同的销售价值列。我正在尝试从日期字段创建它们。
  • 提供表结构。
  • 三栏:|客户 ID |金额 |日期 |
【解决方案3】:

MySQL 为 GROUP BY 子句提供 WITH ROLLUP 修饰符。 Take a look at this.

... GROUP BY customer_id WITH ROLLUP

希望对你有帮助。

【讨论】:

    【解决方案4】:

    试试这个代码。

    选择Customer_id,SUM(金额),MONTHNAME(日期) 来自sales_table 按月分组(日期);

    【讨论】:

    • 谢谢!但是这个查询没有提供每个 Customer_id 的总和,但它确实对当月的总金额进行了分组。
    • 尝试添加 GROUP BY MONTH(date), Customer_id
    • 谢谢,但不是我想要的
    【解决方案5】:

    这个查询得到想要的结果:

    SELECT Customer_id,
    
    Sum(CASE WHEN MONTH(date) = 1 THEN amount END) AS Jan,
    Sum(CASE WHEN MONTH(date) = 2 THEN amount END) AS Feb,
    Sum(CASE WHEN MONTH(date) = 3 THEN amount END) AS Mar,
    ...
    
    FROM table_name
    
    GROUP BY Customer_id
    

    感谢@shawnt00 的提醒;)

    【讨论】:

      【解决方案6】:

      如果您在 Piotr 的答案中像这样更改每一行

      sum(if(month(date) = 1, amount, 0))  AS Jan,
      

      sum(if((month(date) = 1 AND year(date) = 2017 ),  amount,0))  AS Jan_17,
      

      超过一年的数据可以拆分表

      【讨论】:

      • 如果您想对已接受的答案进行小改动,请尝试编辑答案,而不是添加新答案。人们通常只看第一个答案,也许是第二个,所以他们不太可能注意到你的建议。在编辑答案时,最好在最后添加您的建议,并指出这是一个补充
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-04
      • 1970-01-01
      • 1970-01-01
      • 2020-02-21
      • 1970-01-01
      相关资源
      最近更新 更多