【问题标题】:MySQL: Select value where date between two dates. If date/value does not exist display date and value 0MySQL:选择两个日期之间的日期值。如果日期/值不存在,则显示日期和值 0
【发布时间】:2018-03-13 14:06:20
【问题描述】:

我有这张桌子:

+------------+---------+--------+----------+
| 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

得到以下结果:

+------------+-------+
| 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

【问题讨论】:

  • 考虑处理应用代码中数据显示的问题
  • 您生成的日期范围是 3 月 1 日到 3 月 8 日,但您表格中的数据是从 1 月 1 日到 1 月 9 日。尝试生成一月的日期范围。祝你好运!
  • @Brayden 显示的日期是一个示例。如果您使用“正确”日期尝试了代码本身,它会给您任何结果。
  • @Strawberry 什么意思?
  • @jQuerybeast 不,这段代码恰恰相反:从长远来看,它会降低性能,因为它不能扩展。每次运行此代码时,联合子查询都会创建一个临时表。

标签: mysql sql date left-join


【解决方案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() 修复您的版本,但我发现逻辑难以遵循,查询的一部分中的日期与当前日期相关,而另一部分中的日期为固定日期。

【讨论】:

  • 非常聪明,没有考虑将 NOW() 作为时间组件。谢谢
猜你喜欢
  • 2019-11-01
  • 2020-04-07
  • 1970-01-01
  • 2018-12-07
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2016-06-10
相关资源
最近更新 更多