【问题标题】:SQL Find entries WHERE a specific day is on or between dateTimeStart and dateTimeFinishSQL 查找特定日期在 dateTimeStart 和 dateTimeFinish 之间或之间的条目
【发布时间】:2019-08-12 19:00:11
【问题描述】:

我希望运行一个查询来获取在特定日期出现的所有行。

例如,如果我想要 2019 年 3 月 21 日发生的所有条目,则查询应该返回这两个条目。

关于如何做到这一点的任何想法?

【问题讨论】:

  • @AbraCadaver 都只适用于第一个条目,而不是第二个。
  • WHERE '2019-03-21' BETWEEN DATE(StartDateTime) AND DATE(EndDateTime)

标签: php mysql sql date phpmyadmin


【解决方案1】:

由于您只有DATE(没有时间)并且您需要检查DATETIME,然后忽略时间。提取DATETIME 列的DATE 部分并检查您的日期是否在这些日期之间:

SELECT * FROM table_name
         WHERE '2019-03-21' BETWEEN DATE(StartDateTime) AND DATE(EndDateTime)

反之亦然:

SELECT * FROM table_name
         WHERE CAST('2019-03-21' AS DATETIME) BETWEEN StartDateTime AND EndDateTime

【讨论】:

  • 在函数中包装列会妨碍 MySQL 有效利用索引;我们通常更喜欢在谓词中使用裸列。它对平凡集没有影响,但对非平凡集的性能影响可能很大。
【解决方案2】:

你想要:

where '2019-03-21' <= date(enddatetime) and
      '2019-03-21' >= date(startDatetime)

但是,编写查询的最有效方法是:

where enddatetime >= date('2019-03-21') and
      startdatetime < date('2019-03-21') + interval '1 day'

【讨论】:

  • 您是否需要将 DATE() 包裹在 cols 周围,因为他有日期时间,或者 mysql 是否可以正常工作?
  • 这对我来说似乎是合理的,不知道为什么这个答案被否决了。 +10
【解决方案3】:

我们需要检查行中日期时间值的重叠,包括开始日期时间和结束日期时间

在视觉上,给定我们要检查重叠的开始和结束,有几种可能性:

     start       end
       |          | 
  s--e |          |             no overlap
  s----e          |             overlap (*)
  s--------e      |             overlap
  s---------------e             overlap
  s------------------e          overlap
       s---e      |             overlap
       s----------e             overlap
       s-------------e          overlap
       |  s---e   |             overlap
       |  s-------e             overlap
       |  s----------e          overlap
       |          s----e        overlap (*)
       |          |  s---e      no overlap

要找到不重叠的行(假设 start_date_time 总是在 end_date_time 之前,并且两者都不为空),我们可以使用这样的测试:

  WHERE r.end_date_time    <  '2019-03-21 00:00'
     OR r.start_date_time  >= '2019-03-22 00:00'

如果行上的“结束”是我们要测试的范围的开始之前,则没有重叠。或者,如果行上的“开始”在范围的末尾上或之后,则没有重叠。

这是在 2019 年 3 月 21 日随时检查是否有任何重叠。 (“开始”是 3/21,“结束”是 3/22。)

反转该条件会给我们确实重叠的行:

  WHERE NOT ( r.end_date_time    <  '2019-03-21 00:00'
           OR r.start_date_time  >= '2019-03-22 00:00'
            )

可以改写的:

  WHERE  r.end_date_time    >= '2019-03-21 00:00'
    AND  r.start_date_time  <  '2019-03-22 00:00'

(请注意,如果 start_date_time 和/或 end_date_time 的值可以为 NULL,或者 end_date_time 可以在 start_date_time 之前,我们需要更详细的条件。)

【讨论】:

  • 一旦我们开始思考如何检查重叠,条件的语法自然就会消失。只是处理这些边界条件的细节,如果唯一的重叠正好在范围开始/结束的第二个。我通常用这种模式做范围:dt &gt;= start AND dt &lt; end,检查“小于”范围的结尾(例如,使用第二天的午夜,第一秒不在范围内。)
  • 同样的模式适用于检查任何范围的重叠,而不仅仅是“天”。其他使用 DATE() 函数的解决方案(以取消日期时间值的时间)可以在特殊情况下检查仅在一天与午夜边界重叠的情况。例如如果我们需要检查与 3/21 8AM 和 3/21 3PM 或 3/25 5AM 的范围重叠怎么办,...
【解决方案4】:

可以使用日期功能:

SELECT * from table where date(my_date) = '2019-03-21'

来源:date

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 2012-05-27
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    相关资源
    最近更新 更多