mySQL Between Time Range - 开始时间可以大于结束时间

mySQL Between Time Range - Where start time can be greater than end time

提问人:imvain2 提问时间:8/18/2023 最后编辑:imvain2 更新时间:8/19/2023 访问量:45

问:

我尝试在 SO 中搜索这个问题,但找不到与 mySQL 相关的任何内容。

我有一个包含各种数据的表格,但对于这个问题,相关数据是星期几、开始时间和结束时间。

我正在尝试获取与一周中某一天匹配的记录,其中 now() 在匹配的时间范围内。但是,问题是开始时间可以大于结束时间,反之亦然,或者时间也可能只是 00:00:00。

表格的相关字段和示例数据:page_data

field_value | start_time | end_time
------------+------------+---------
Monday      | 17:00:00   | 08:00:00
Tuesday     | 17:00:00   | 08:00:00
Wednesday   | 17:00:00   | 08:00:00
Thursday    | 17:00:00   | 08:00:00
Friday      | 17:00:00   | 08:00:00
Saturday    | 00:00:00   | 00:00:00
Sunday      | 00:00:00   | 00:00:00

几点说明:

  • 00:00:00 - 00:00:00 基本上意味着全天跑步
  • 如果开始时间大于结束时间,例如 17:00 - 8:00,则会 意思是从下午 5 点跑到第二天早上 8 点。

我试过了,但这并不涵盖start_time > end_time。now() between start_time and end_time

以下是我到目前为止所拥有的,但它在不应该返回的时候返回。

10:00:00 是一个测试时间,不应返回任何内容,但它确实返回。

为了测试,我硬编码了一个时间,而不是使用now()

如果我删除,那么start_time更大不会返回任何东西。or ('10:00:00' between end_time and start_time)

select * from page_data
where field_value = 'Friday'
and (
    (start_time = '00:00:00' and end_time = '00:00:00') or
    ('10:00:00' between start_time and end_time) or
    ('10:00:00' between end_time and start_time)
)

我对可用于考虑以下注意事项的查询感到困惑:

  • 开始时间>结束时间
  • 结束时间>开始时间
  • 结束时间和开始时间 = 00:00:00

谢谢

mysql 日期时间

评论

0赞 pilcrow 8/18/2023
end_time < start_time时,在您的数据集中意味着什么?这是否意味着记录的事件在某一天开始,在第二天结束?为什么午夜是开始和结束的特例?这在数据集中是什么意思?
0赞 imvain2 8/18/2023
@pilcrow 对于缺乏上下文,我深表歉意。此表供网站确定何时显示通知。默认值实际上只是转换为 00:00:00,实际上只是这个项目的一个非常具体的用例。那部分我知道我做了其他事情,比如默认值 NULL 等。我更关注开始时间大于结束时间,反之亦然。我没有存储日期时间对象,因为这些对象不是特定于日期的。
0赞 pilcrow 8/19/2023
因此,确实意味着通知应该从周三开始显示。从下午 5 点到第二天早上 8 点?双午夜的意思是,“总是在给定的一天出现”?显示示例值以及您希望选择的行会很有帮助。('Weds', '17:00', '08:00')
0赞 imvain2 8/19/2023
@pilcrow感谢您的编辑和提问。你的假设是对的,我确实澄清了这个问题上的那些事情。
0赞 Rob Eyre 8/19/2023
那么,如果start_time > end_time,NOW() 不应该介于 end_time 和 start_time 之间是正确的逻辑吗?

答:

1赞 Rob Eyre 8/19/2023 #1

在start_time > end_time的情况下,我猜你只想匹配test_time大于 start_time 或小于 end_time。这在逻辑上等同于end_time和start_time之间的test_time NOT。

如果此逻辑正确,则可能需要以下代码:

select * from page_data
where field_value = 'Friday'
and (
    (start_time = '00:00:00' and end_time = '00:00:00') or
    (start_time < end_time) and ('10:00:00' between start_time and end_time) or
    (start_time > end_time) and NOT('10:00:00' between end_time and start_time)
)

评论

0赞 imvain2 8/19/2023
哦,哇,这行得通,谢谢。我太专注于两者之间了,以至于我从未想过相反的情况。
0赞 pilcrow 8/21/2023
这将返回周一上午 7:30 的比赛,这不是数据所说的。
0赞 pilcrow 8/19/2023 #2

你喜欢这个吗?

SELECT ...
  FROM easier_to_work_with
 WHERE day_of_week = DAYNAME(CURRENT_DATE)
       AND
       CURRENT_TIME BETWEEN start_time AND end_time;

在我看来,将“通知窗口”周期指定为限制在一天内的时间间隔会更容易,将跨越一天以上的窗口表示为两个相邻的窗口。

然后,您只需根据窗口检查当前日期和当前时间即可。

您可以在不更改现有应用程序逻辑或现有表结构的情况下执行此操作:

CREATE VIEW easier_to_work_with AS
     -- get same day windows
     SELECT ..., field_value as day_of_week, start_time, end_time
       FROM page_data
      WHERE start_time < end_time
      UNION
     -- get all day windows, or partials crossing midnight
     SELECT ..., field_value, start_time, '23:59:59'
       FROM page_data
      WHERE (start_time = '00:00:00' AND end_time = '00:00:00')
              OR
            end_time < start_time
      UNION
     -- get carryover windows from the previous day
     SELECT ...,
            CASE field_value
              WHEN 'Monday'    THEN 'Tuesday'
              WHEN 'Tuesday'   THEN 'Wednesday'
              WHEN 'Wednesday' THEN 'Thursday'
              WHEN 'Thursday'  THEN 'Friday'
              WHEN 'Friday'    THEN 'Saturday'
              WHEN 'Saturday'  THEN 'Sunday'
              WHEN 'Sunday'    THEN 'Monday'
            END, '00:00:00', end_time
       FROM page_data
      WHERE end_time < start_time;