【问题标题】:How to print each day of the week as Column 1 in a MySQL query where not all days have a result如何在 MySQL 查询中将一周中的每一天打印为第 1 列,其中并非所有天都有结果
【发布时间】:2012-09-29 08:00:53
【问题描述】:

我有以下查询,显示一周中每一天的计费小时数

SELECT DAYNAME(record_date),
      sum(value)
FROM acx_time_records
WHERE
  acx_time_records.state = 3
  AND record_date >= '2012-10-1' AND record_date <= '2012-10-7'    
  AND user_id = 7 
  GROUP BY
  dayname(acx_time_records.record_date)
  ORDER BY weekday(acx_time_records.record_date)

以上查询输出如下结果:

Tuesday    9.75
Friday     1

我遇到的问题是我需要将值绘制到已经将 X 轴定义为一周中的每一天的图表:

 Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday

因此,我需要传递一周中的每一天以获得结果,而不仅仅是结果中显示的特定日期/时间。我考虑过加入一个新表,该表具有一周中的每个日历日和一天索引,但我不确定这怎么可能。理想的输出是:

Monday    0
Tuesday   9.75
Wednesday 0
Thursday  0
Friday    1
Saturday  0
Sunday    0

任何关于我如何完成此任务的提示/建议将不胜感激。我知道这也可以通过将 MySQL 与 PHP 相结合来促进,但我正在尝试以一种只需要 MySQL 的方式来实现这一点。

【问题讨论】:

    标签: mysql left-join inner-join outer-join


    【解决方案1】:

    我实际上建议您按照您最初的想法加入另一个表,但您可以使用 LEFT JOIN 子句将其变成一个简单的别名表:

    SELECT
        days.day,
        IF (value IS NULL, 0, SUM(value))
    FROM
        (SELECT 'Monday' AS day UNION SELECT 'Tuesday' UNION SELECT 'Wednesday' UNION SELECT 'Thursday' UNION SELECT 'Friday' UNION SELECT 'Saturday' UNION SELECT 'Sunday') AS days
        LEFT JOIN (
            SELECT * FROM acx_time_records
            WHERE 
                acx_time_records.state = 3
                AND record_date >= '2012-10-1' AND record_date <= '2012-10-7'    
                AND user_id = 7 
        ) AS acx_time_records
            ON DAYNAME(record_date) = days.day
    GROUP BY
        days.day
    ORDER BY weekday(acx_time_records.record_date)
    

    这将导致一周中的每一天都被选中(作为单独的行),并且每个 SUM(),如果没有定义日期,0 将被相应地分组。

    【讨论】:

    • 这仍然只返回周二和周五的结果。不知道为什么会这样。有什么想法吗?
    • 在您的示例中,价值是否来自日表?还是来自 acx_time_records 表?在我的代码中,它来自 acx_time_records.values
    • @DanielC 对不起,昨晚很早就签了。看起来它不起作用,因为您的 WHERE 子句限制了返回的实际天数;如果您将acx_time_records 放入带有WHERE 子句的子选择中并加入它,它将起作用(我已经更新了我的答案以显示)。此外,value 来自 acx_time_records 表 - days 表中唯一的内容是当天的名称。
    • 谢谢@newfurniturey - 这似乎是问题所在。我选择的答案包括在适当位置的 WHERE 子句。也感谢您的帮助!
    【解决方案2】:

    LEFT JOIN 的解决方案。

    您可以按照 newfurniturey 的建议使用附加表或使用一些带有 UNION 的 SELECT。我还在连接表中找到了 WHERE 过滤器。

    CREATE TABLE week_days(
      week_day_num INT(11) DEFAULT NULL
    );
    
    INSERT INTO week_days(week_day_num) VALUES (1),(2),(3),(4),(5),(6),(7);
    
    SELECT
      DAYNAME(atrrecord_date),
      SUM(atr.value),
      COALESCE(SUM(atr.value) , 0)
    FROM week_days wd
      LEFT JOIN (
          SELECT * FROM acx_time_records
          WHERE
            acx_time_records.state = 3
            AND record_date >= '2012-10-1' AND record_date <= '2012-10-7'    
            AND user_id = 7 
        ) atr
        ON wd.week_day_num = DAYOFWEEK(atr.record_date)
    GROUP BY
      DAYOFWEEK(atr.record_date);
    

    【讨论】:

    • 行得通!连接表中的 WHERE 过滤器起到了作用。谢谢。如果某一天 (atr.value) 的结果为 Null,您对如何将 0 显示为值有什么建议吗?
    • 尝试使用 COALESCE 功能,例如COALESCE(SUM(atr.value) , 0).
    • 我应该把那个函数放在哪里?
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多