我正在尝试聚合一些通话记录并做错事 - 但不确定是什么。
我有以下查询:
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 |
+--------------------------------+----------+------+------+--------+------+------+------+
我做错了什么?
答案 0 :(得分:3)
像这样改变
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;
答案 1 :(得分:1)
你想:
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
这是一个更合乎逻辑的分支..但我不确定哪个会更快,因为*
操作,基准测试可能很有趣。 IF
也仅限于MySQL,您可以使用标准CASE
。
我可以承认有些人可能会发现IF/CASE
比使用BOOLEAN
=>更具可读性1
,0
动态,再次可能仅限于MySQL。
我还在列上添加了表别名,将GROUP BY
更改为更明显的c.name
并使用了明确的JOIN
。
这些是可读性问题..
包含表别名意味着您可以单独读取查询并知道每列的来源...例如在发布问题时!我不得不假设start
和duration
来自call_history
,这在这里无所谓,但在其他问题上绝对可以。
我倾向于GROUP BY
MySQL SELECT
中的非聚合列,以确保我没有遗漏任何内容。如果我错了,请纠正我,但我认为其他引擎需要它。如果您有c.name
个重复内容,我会同时选择c.id
和c.name
以及GROUP BY
,以消除任何混淆。
至于使用隐式JOIN
,您可以看到讨论here