MySql根据员工在“费用类型”组中的值,从“费用”表中汇总不同类型的费用

时间:2017-08-16 00:10:44

标签: mysql sql join case

这篇文章的更通用的标题是

  

MySql根据另一行的值,按另一行的值

对同一表中的不同列求和

我有一份员工开支表:

id | employee_id | expense_cat_id | expense_amount |
 1  | 11          | 1              | 100            |
 2  | 11          | 1              | 200            |
 3  | 12          | 1              | 120            |
 4  | 12          | 1              | 140            |
 5  | 11          | 2              | 5              |
 6  | 12          | 2              | 8              |`

我希望制作一份这样的报告:

Employee Id | Expense Cat 1 Total Amount | Expense Cat 2 Total Amount 11 | 300 | 5 12 | 260 | 8

所以最初我认为我可以在同一个表中使用2个表别名:

SELECT employee_id, sum(expense_cat_1.expense_amount) as expense_1_total, sum(expense_cat_2.expense_amount) as expense_2_total FROM expenses as expense_cat_1 where expense_cat_1.expense_cat_id=1 , expenses as expense_cat_2 where expense_cat_2.expense_cat_id=2 group by employee_id

但这不是正确的Sql语法,这对我来说很有意义。

所以我认为我可以在employee表和费用表之间进行两次连接:

SELECT employees.id as employee_id, sum(expenses_cat_1.expense_amount) as expense_1_total, sum(expenses_cat_2.expense_amount) as expense_2_total FROM employees join expenses as expenses_cat_1 on employees.id = expenses_cat_1.employee_id and expenses_cat_1.expense_cat_id=1 join expenses as expenses_cat_2 on employees.id = expenses_cat_2.employee_id and expenses_cat_2.expense_cat_id=2 group by employees.id

哪个接近,但是错了:

employee_id | expense_1_total | expense_2_total 11 | 300 | 10 12 | 260 | 16

因为费用2总计加倍!我认为这是因为连接为类别1的两个费用中的每一个显示两行,并将它们相加。

我还尝试了一种子查询方法:

SELECT (SELECT sum(expense_amount) FROM expenses WHERE expense_cat_id = 1) AS sum1 , (SELECT sum(expense_amount) FROM expenses WHERE expense_cat_id = 2) AS sum2, employee_id FROM expenses group by employee_id

但这与连接方法有同样的问题 - cat 2的总数加倍。

如何使第二次加入仅包括expense_2_total一次???

我个人不喜欢sql case语句,因为它们看起来更像是一个过程语言结构(并且sql是声明性的),但很高兴考虑在这种情况下使用它们 - 但我把挑战放在那里为sql专家优雅地解决这个问题。

1 个答案:

答案 0 :(得分:0)

您正在寻找条件聚合:

SELECT employee_id,
       sum(case when expense_cat_id = 1 then expense_amount else 0 end) as expense_1_total,
       sum(case when expense_cat_id = 2 then expense_amount else 0 end) as expense_2_total
FROM expenses e
GROUP BY employee_id;