您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Mysql:按小时分组,如果没有数据,则为0

Mysql:按小时分组,如果没有数据,则为0

首先,您的查询可以用一种更简单的方式表示为:

SELECT COUNT(*) AS totalCalls, HOUR(`end`) AS `Hour`
FROM callsDataTable c
  INNER JOIN products p ON c.company = p.number
    AND p.id IN (@_PRODUCTS)
    AND YEAR(`end`) = @_YEAR AND MONTH(`end`) = @_MONTH
GROUP BY HOUR(`end`) AS `Hour`
ORDER BY `Hour` ASC

使用@NoDisplayName在他们的答案中提出的想法:

CREATE TABLE hours_table (hours INT);

INSERT INTO hours_table VALUES(0), (1), (2), 
    /* put the missing values here */ (23);

您可以加入包含小时数的表,以获取所需的结果:

SELECT COUNT(*) AS totalCalls, h.hours AS `Hour`
FROM callsDataTable c
  INNER JOIN products p ON c.company = p.number
  RIGHT JOIN hours_table h ON h.hours = HOUR(c.`end`)
    AND p.id IN (@_PRODUCTS)
    AND YEAR(`end`) = @_YEAR AND MONTH(`end`) = @_MONTH
GROUP BY h.hours
ORDER BY h.hours ASC

如果运行太慢(我确定运行速度很慢),则应该研究一种使用类似方法方法end BETWEEN '2015-01-01 00:00:00' AND '2015-01-31 23:59:59'而不是比较YEAR(end)MONTH(end)

可以这样完成:

SET @start = STR_TO_DATE(CONCAT(@_YEAR, '-', @_MONTH, '-01 00:00:00'), '%Y-%m-%d %H:%i:%s');
SET @end   = DATE_SUB(DATE_ADD(@start, INTERVAL 1 MONTH), INTERVAL 1 SECOND);

SELECT ...
...
    AND `end` BETWEEN @start AND @end
...

但是这种改变本身并没有帮助。它需要一个现场索引end来带来所需的速度改进:

ALTER TABLE callsDataTable ADD INDEX(end);

使用HOUR(c.end)的连接条件是另一个原因运行缓慢。

可以通过将表hours_table与第一个查询(的简化版本)生成的结果集结合在一起来进行改进:

SELECT IFNULL(totalCalls, 0) AS totalCalls, h.hours AS `Hour`
FROM hours_table h
   LEFT JOIN (
        SELECT COUNT(*) AS totalCalls, HOUR(`end`) as `Hour`
        FROM callsDataTable c
          INNER JOIN products p ON c.company = p.number
            AND p.id IN (@_PRODUCTS)
            AND YEAR(`end`) = @_YEAR AND MONTH(`end`) = @_MONTH
        GROUP BY HOUR(`end`) AS `Hour`
   ) d ON h.hours = d.`Hour`
ORDER BY h.hours ASC
MySQL 2022/1/1 18:43:09 有356人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶