MySQL:选择两个日期之间的日期值。如果日期/值不存在,则显示日期和值0

时间:2018-03-12 23:02:13

标签: mysql sql date left-join

我有这张桌子:

+------------+---------+--------+----------+
| date       | regular | deduct | overtime |
+------------+---------+--------+----------+
| 2018-01-01 | 8       | 0      | 0        |
+------------+---------+--------+----------+
| 2018-01-03 | 8       | 0      | 0        |
+------------+---------+--------+----------+
| 2018-01-04 | 8       | 0      | 1        |
+------------+---------+--------+----------+
| 2018-01-09 | 8       | 2      | 0        |
+------------+---------+--------+----------+

我想选择:

  1. 2018-01-01和2018-01-09之间的所有内容
  2. 小时=常规 - 扣除+加班
  3. 如果未找到日期,则显示小时= 0
  4. 获得以下结果:

    +------------+-------+
    | date       | hours |
    +------------+-------+
    | 2018-01-01 | 8     |
    +------------+-------+
    | 2018-01-02 | 0     |
    +------------+-------+
    | 2018-01-03 | 0     |
    +------------+-------+
    | 2018-01-04 | 9     |
    +------------+-------+
    | 2018-01-05 | 0     |
    +------------+-------+
    | 2018-01-06 | 0     |
    +------------+-------+
    | 2018-01-07 | 0     |
    +------------+-------+
    | 2018-01-08 | 0     |
    +------------+-------+
    | 2018-01-09 | 6     |
    +------------+-------+
    

    这是用于生成两个日期之间的一系列日期的SQL:

    SELECT DATE(cal.date) as date
    FROM ( 
          SELECT SUBDATE(NOW(), INTERVAL 60 DAY) + INTERVAL xc DAY AS date 
          FROM ( 
                SELECT @xi:=@xi+1 as xc from 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc1, 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc2, 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc3, 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc4, 
                (SELECT @xi:=-1) xc0 
          ) xxc1 
    ) cal 
    WHERE cal.date >= '2018-01-01' and cal.date <= '2018-01-09'
    GROUP BY DATE(cal.date)
    ORDER BY cal.date ASC
    

    这就是我尝试加入上面的表格而没有结果的时间:

    SELECT DATE(cal.date) as date, IFNULL((x.regular + x.overtime - x.deduct), 0) AS hours 
    FROM ( 
          SELECT SUBDATE(NOW(), INTERVAL 60 DAY) + INTERVAL xc DAY AS date 
          FROM ( 
                SELECT @xi:=@xi+1 as xc from 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc1, 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc2, 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc3, 
                (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) xc4, 
                (SELECT @xi:=-1) xc0 
          ) xxc1 
    ) cal 
    LEFT JOIN attendance x ON x.date = cal.date
    WHERE cal.date >= '2018-01-01' and cal.date <= '2018-01-09'
    GROUP BY DATE(cal.date)
    ORDER BY cal.date ASC
    

1 个答案:

答案 0 :(得分:1)

这是一个简单的修复:

SELECT DATE(cal.date) as date, IFNULL((x.regular + x.overtime - x.deduct), 0) AS hours 
FROM (SELECT (DATE('2018-01-01') + INTERVAL xc DAY) AS date 
      FROM (SELECT (@xi := @xi + 1) as xc 
            FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) xc1 CROSS JOIN
                 (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) xc2 CROSS JOIN
                 (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) xc3 CROSS JOIN 
                 (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) xc4 CROSS JOIN 
                 (SELECT @xi:=-1) xc0 
           ) xxc1 
     ) cal LEFT JOIN
     attendance x
     ON x.date = cal.date
WHERE cal.date >= '2018-01-01' and cal.date <= '2018-01-09'
GROUP BY DATE(cal.date)
ORDER BY cal.date ASC;

问题在于JOINNOW()NOW()作为时间组件,因此JOIN将始终失败(好吧,除非您在午夜时分运行)。

您可以使用CURDATE()修复您的版本,但我发现逻辑难以理解,在查询的一部分中相对于现在的日期和在另一部分中的固定日期。