MySQL聚合查询的行为不符合预期

MySQL聚合查询的行为不符合预期,mysql,sql,Mysql,Sql,我正在尝试汇总一些通话记录,并做了一些错误的事情-但不确定是什么 我有以下疑问: SELECT c.name, IF(MONTH(start) = 1, SUM(duration),0) AS 'Jan', IF(MONTH(start) = 2, SUM(duration),0) AS 'Feb', IF(MONTH(start) = 3, SUM(duration),0) AS 'Mar', IF(MONTH(start) = 4, SUM(dur

我正在尝试汇总一些通话记录,并做了一些错误的事情-但不确定是什么

我有以下疑问:

SELECT 
    c.name, 
    IF(MONTH(start) = 1, SUM(duration),0) AS 'Jan',
    IF(MONTH(start) = 2, SUM(duration),0) AS 'Feb',
    IF(MONTH(start) = 3, SUM(duration),0) AS 'Mar',
    IF(MONTH(start) = 4, SUM(duration),0) AS 'Apr',
    IF(MONTH(start) = 5, SUM(duration),0) AS 'Jun',
    IF(MONTH(start) = 6, SUM(duration),0) AS 'Jul',
    IF(MONTH(start) = 7, SUM(duration),0) AS 'Aug'
FROM
    call_history ch, client c
WHERE
    ch.client_reseller_id = c.id
GROUP BY ch.client_reseller_id
ORDER BY c.name;
start
字段包含通话的日期/时间。该表只包含一年的记录,因此不必担心不按年份过滤

我得到的结果与预期不符:

+--------------------------------+----------+------+------+--------+------+------+------+
| name                           | Jan      | Feb  | Mar  | Apr    | Jun  | Jul  | Aug  |      
|+-------------------------------+----------+------+------+--------+------+------+------+
| Come company                   |  5243080 |    0 |    0 |      0 |    0 |    0 |    0 |
| Other cust                     |  4085085 |    0 |    0 |      0 |    0 |    0 |    0 |
| Someone                        |  1449543 |    0 |    0 |      0 |    0 |    0 |    0 |
| Demo Reseller                  |     2342 |    0 |    0 |      0 |    0 |    0 |    0 |
+--------------------------------+----------+------+------+--------+------+------+------+
我做错了什么?

像这样改变

SELECT 
    c.name, 
   SUM(IF(MONTH(start) = 1, duration,0)) AS 'Jan',
    SUM(IF(MONTH(start) = 2, duration,0)) AS 'Feb',
    SUM(IF(MONTH(start) = 3, duration,0)) AS 'Mar',
    SUM(IF(MONTH(start) = 4, duration,0)) AS 'Apr',
    SUM(IF(MONTH(start) = 5, duration,0)) AS 'Jun',
    SUM(IF(MONTH(start) = 6, duration,0)) AS 'Jul',
    SUM(IF(MONTH(start) = 7, duration,0)) AS 'Aug'
FROM
    call_history ch, client c
WHERE
    ch.client_reseller_id = c.id
GROUP BY ch.client_reseller_id
ORDER BY c.name;
像这样改变

SELECT 
    c.name, 
   SUM(IF(MONTH(start) = 1, duration,0)) AS 'Jan',
    SUM(IF(MONTH(start) = 2, duration,0)) AS 'Feb',
    SUM(IF(MONTH(start) = 3, duration,0)) AS 'Mar',
    SUM(IF(MONTH(start) = 4, duration,0)) AS 'Apr',
    SUM(IF(MONTH(start) = 5, duration,0)) AS 'Jun',
    SUM(IF(MONTH(start) = 6, duration,0)) AS 'Jul',
    SUM(IF(MONTH(start) = 7, duration,0)) AS 'Aug'
FROM
    call_history ch, client c
WHERE
    ch.client_reseller_id = c.id
GROUP BY ch.client_reseller_id
ORDER BY c.name;
你想要:

  SELECT c.name, 
         SUM((MONTH(ch.start)=1)*ch.duration) 'Jan',
         SUM((MONTH(ch.start)=2)*ch.duration) 'Feb',
         SUM((MONTH(ch.start)=3)*ch.duration) 'Mar',
         SUM((MONTH(ch.start)=4)*ch.duration) 'Apr',
         SUM((MONTH(ch.start)=5)*ch.duration) 'Jun',
         SUM((MONTH(ch.start)=6)*ch.duration) 'Jul',
         SUM((MONTH(ch.start)=7)*ch.duration) 'Aug'
    FROM call_history ch
    JOIN client c
      ON c.id = ch.client_reseller_id
GROUP BY c.name
ORDER BY c.name;
这使用了一个事实,即在MySQL中布尔值被评估为
true=>1
false=>0

它避免使用另一个逻辑分支的
IF
。。但是由于
*
操作,我不确定哪一个会更快,基准测试可能会很有趣
如果
也仅限于MySQL,则可以使用标准的
案例

我可以承认,有些人可能会发现
IF/CASE
比使用
布尔值
=>
1
0
动态更具可读性,这可能再次被限制为MySQL

我还将表别名包括在列中,将您的
groupby
更改为更明显的
c.name
,并使用显式的
JOIN

这些都是可读性问题

包含表别名意味着您可以单独读取查询,并知道每列的来源。。例如,当发布问题时!我不得不假设
start
duration
来自
call\u history
,这在这里并不重要,但在其他问题上绝对可以

我倾向于在MySQL中选择
中的
非聚合列,以确保没有遗漏任何内容。如果我错了,请纠正我,但我认为其他引擎需要它。如果您有重复的
c.name
s,我将同时选择
c.id
c.name
groupby
以消除任何混淆

关于隐式
JOIN
s的使用,您可以看到您想要的讨论

  SELECT c.name, 
         SUM((MONTH(ch.start)=1)*ch.duration) 'Jan',
         SUM((MONTH(ch.start)=2)*ch.duration) 'Feb',
         SUM((MONTH(ch.start)=3)*ch.duration) 'Mar',
         SUM((MONTH(ch.start)=4)*ch.duration) 'Apr',
         SUM((MONTH(ch.start)=5)*ch.duration) 'Jun',
         SUM((MONTH(ch.start)=6)*ch.duration) 'Jul',
         SUM((MONTH(ch.start)=7)*ch.duration) 'Aug'
    FROM call_history ch
    JOIN client c
      ON c.id = ch.client_reseller_id
GROUP BY c.name
ORDER BY c.name;
这使用了一个事实,即在MySQL中布尔值被评估为
true=>1
false=>0

它避免使用另一个逻辑分支的
IF
。。但是由于
*
操作,我不确定哪一个会更快,基准测试可能会很有趣
如果
也仅限于MySQL,则可以使用标准的
案例

我可以承认,有些人可能会发现
IF/CASE
比使用
布尔值
=>
1
0
动态更具可读性,这可能再次被限制为MySQL

我还将表别名包括在列中,将您的
groupby
更改为更明显的
c.name
,并使用显式的
JOIN

这些都是可读性问题

包含表别名意味着您可以单独读取查询,并知道每列的来源。。例如,当发布问题时!我不得不假设
start
duration
来自
call\u history
,这在这里并不重要,但在其他问题上绝对可以

我倾向于在MySQL中选择
中的
非聚合列,以确保没有遗漏任何内容。如果我错了,请纠正我,但我认为其他引擎需要它。如果您有重复的
c.name
s,我将同时选择
c.id
c.name
groupby
以消除任何混淆


关于隐式
JOIN
s的使用,您可以看到一个讨论

您预期的结果是什么?这是因为您的
分组方式
使用无效(标准)SQL。其他DBMS都会拒绝您的查询,但MySQL会选择返回“随机”(他们称之为不确定)结果,而不会用错误消息来打扰您。有关详细信息,请参见此处:和此处:您的预期结果是什么?这是因为您的
groupby
用法无效(标准)SQL。其他DBMS都会拒绝您的查询,但MySQL会选择返回“随机”(他们称之为不确定)结果,而不会用错误消息来打扰您。有关详细信息,请参见此处:和此处:宾果:)无法查看。非常感谢。宾果:)我看不出来。非常感谢。似乎有些复杂的事情-你的方法有什么好处?@btongeorge。正确的
join
语法不是“复杂因素”。这是一个好处,你应该学会如何使用它。@B Tongeorge我已经提供了我在答案编辑中看到的好处。@Arth感谢你的澄清这是一个有趣的解决方案,我在那里学到了一些东西。投票结果如下:)@GordonLinoff我将了解其中一种方法的优点。谢谢你的指点,我没有冒犯的意思:)看起来事情有点复杂-你的方法有什么好处?@B东乔治。正确的
join
语法不是“复杂因素”。这是一个好处,你应该学会如何使用它。@B Tongeorge我已经提供了我在答案编辑中看到的好处。@Arth感谢你的澄清这是一个有趣的解决方案,我在那里学到了一些东西。投票结果如下:)@GordonLinoff我将了解其中一种方法的优点。谢谢你的指点,我无意冒犯:)