sql null为0,左连接?

uklbhaso  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(367)

问题

我有一个logs表,用户可以在其中输入他们在一个项目上花费的时间(它用于应用程序上的图形和数据表)。我还生成了一个“日历”表,这样我就可以留下连接日期,并用零填充“空”日期。然而,在花了一段时间后,我找不到一个方法去做。。。

表1:日志

id | hoursSpent | logDate 
1    5            2018-08-05
2    1            2018-08-07
3    3            2018-08-10

表2:日历

id         | db_date
20180807     2018-08-07
20180808     2018-08-08
20180809     2018-08-09
201808010    2018-08-10
etc...

期望输出

db_date      | hoursSpent
2018-08-05     5
2018-08-06     0
2018-08-07     1
2018-08-08     0
2018-08-09     0
2018-08-10     3

到目前为止使用的代码(完全不起作用…)

SELECT hoursSpent, db_date
FROM logs LEFT JOIN calendar ON db_date
WHERE db_date BETWEEN '2018-08-10' AND '2018-08-01'
GROUP BY db_date
46qrfjad

46qrfjad1#

使用 LEFT JOIN 是正确的。查询的其余部分需要清理:

SELECT c.db_date, COALESCE(l.hoursSpent, 0) as hoursSpent
FROM calendar c LEFT JOIN
     logs l
     ON c.db_date = l.logdate
WHERE c.db_date BETWEEN '2018-08-01' AND '2018-08-10';

笔记:
你想要所有的行吗 calendar ,所以它应该是 LEFT JOIN .
你需要有效的 ON 连接两个表的条件。 BETWEEN 要求操作数按顺序排列,因此小操作数在 AND 后面越大。 GROUP BY 似乎没必要。 COALESCE() 实际上产生了 0 价值观。
在具有多个表引用的查询中,限定所有列名。

b91juud3

b91juud32#

包含所有必需行的表( Calendar )必须在 LEFT JOIN ,缺少记录的表( Logs )在右边。或者,您可以保持表的顺序,而不是使用 RIGHT JOIN .
当查询中有多个表时,使用别名消除歧义非常有用。
完整的 ON 子句需要比较。
指定的范围 BETWEEN 条件必须按升序排列。
这个 GROUP BY 子句要求将聚合函数应用于 SELECT -列表。在这里 SUM 功能合适。自从 SUM 函数返回 NULL 如果没有匹配的记录,我们应用 COALESCE 函数将它们转换为 0 s。

SELECT
    c.db_date, COALESCE(SUM(l.hoursSpent), 0) AS hoursSpent
FROM
    Calendar c
    LEFT JOIN Logs l
        ON c.db_date = l.logDate
WHERE
    c.db_date BETWEEN '2018-08-01' AND '2018-08-10'        
GROUP BY
    c.db_date;

请参见sql fiddle:http://sqlfiddle.com/#!9/d28de9c/3/0型

1hdlvixo

1hdlvixo3#

你的加入顺序不对, calendar 应位于左侧,因为应包括其所有行,而不考虑来自的匹配行 logs . 转变 NULL 进入 0 使用 coalesce() . 如果你 GROUP BY 对于日期,必须对其应用聚合函数 hoursspent . 我猜你想 sum() .

SELECT c.db_date,
       sum(coalesce(l.hoursspent, 0)) hoursspent
       FROM calendar c
            LEFT JOIN logs l
                      ON l.logdate = c.db_date
       WHERE c.db_date BETWEEN '2018-08-10'
                               AND '2018-08-01'
       GROUP BY c.db_date;

这里你也可以省略 coalesce() 作为mysql的 sum() 对待 NULL 作为 0 不管怎样。
但样本数据表明,你也许不需要这么做 GROUP BY 如果同一天没有多个日志条目,也就是说。

SELECT c.db_date,
       coalesce(l.hoursspent, 0) hoursspent
       FROM calendar c
            LEFT JOIN logs l
                      ON l.logdate = c.db_date
       WHERE c.db_date BETWEEN '2018-08-10'
                               AND '2018-08-01';

相关问题