【问题标题】:Select all stores open at current time选择在当前时间营业的所有商店
【发布时间】:2016-07-17 09:59:30
【问题描述】:

我有一个名为 opening_hours 的表,如下所示:

id int(11), weekday int(1), start_hour time, end_hour time

我使用这个查询来选择所有现在正在营业的商店:

SELECT * FROM shops s 
INNER JOIN opening_hours o 
ON ( s.id = o.id ) 
AND ( o.weekday = WEEKDAY(CURDATE()) + 1 ) 
AND ( ( CURTIME() >= o.start_hour ) AND ( CURTIME() <= o.end_hour ) ) 

我的问题是,当商店在午夜后营业时,这个查询给出了错误的结果。那是因为午夜之后的时间早于午夜之前的时间。如何处理?

【问题讨论】:

    标签: mysql sql database database-design logic


    【解决方案1】:

    正确的逻辑更复杂。如果营业时间跨越两个日期,那么在凌晨时分,您必须查看天的营业时间 -- 除非您假设每天的营业时间都相同(但那为什么有桌子?)。

    条件更像这样:

    SELECT *
    FROM shops s INNER JOIN
         opening_hours o 
         ON s.id = o.id
    WHERE ((o.weekday = weekday(curdate()) + 1) and
           ((o.end_hour > o.start_hour and curtime() >= o.start_hour and curtime <= o.end_hour) or
            (o.end_hour < o.start_hour and curtime() >= o.start_hour)
           ) or
          (o.weekday = weekday(date_add(curdate(), interval 1 day))  + 1 and
           o.end_hour < o.start_hour and
           curtime() <= o.end_Hour
          );
    

    三个条件是:

    • 一天的营业时间
    • 开放时间为两天,且不早于开放时间
    • 营业时间跨度两天,时间早于打烊时间

    【讨论】:

    • 非常感谢戈登!但是你能解释一下接受的答案是如何失败的吗?我不明白为什么你的答案效果更好。
    • @Droabs 。 . .接受答案失败,因为诸如“星期一,上午 10:00 - 凌晨 2:00”之类的条目正在检查周二凌晨 1:00 的 Tuesday 记录。它不检查 Monday 记录。日期比较还需要在午夜后的几个小时内进行调整(并且此查询中的日期比较可能会出现差一错误)。
    • 谢谢!如果每周营业时间为“5:00 am - 1:00 am”,则此解决方案不起作用。
    【解决方案2】:

    end_hour 小于start_hour 时,您必须修改end_hour 使其大于start_hour

    实现这一点的一种方法是当end_hour小于start_hour时从24:00:00中减去end_hour,否则以end_hour为准。

    SELECT * FROM shops s 
    INNER JOIN opening_hours o 
    ON ( s.id = o.id ) 
    AND ( o.weekday = WEEKDAY(CURDATE()) + 1 ) 
    AND ( ( CURTIME() >= o.start_hour ) AND ( CURTIME() <= IF(o.end_hour < o.start_hour,TIMEDIFF(TIME('24:00:00'),o.end_hour),o.end_hour ) ) ) ;
    

    编辑:end_hour00:00:00 时,上面的查询执行得很好。

    但在这种情况下它可能会给出错误的输出

    start_hour = 07:00:00 &amp; end_hour = 02:00:00.

    那么,这里你可以如何恢复(在你的主查询中使用这个条件):

    AND 
    ( 
      IF(o.end_hour < o.start_hour, 
      ( CURTIME() >= o.start_hour ) OR ( CURTIME() <= o.end_hour ),
      ( CURTIME() >= o.start_hour ) AND ( CURTIME() <= o.end_hour )
    ) 
    

    请注意,如果范围位于同一日期,则应以以下条件为准:

    ( CURTIME() &gt;= o.start_hour ) AND ( CURTIME() &lt;= o.end_hour ).

    如果范围在午夜结束,那么这个条件应该起作用:

    ( CURTIME() &gt;= o.start_hour ) OR ( CURTIME() &lt;= o.end_hour )

    【讨论】:

    • 太好了。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2010-10-20
    • 2015-11-23
    • 2011-11-09
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    相关资源
    最近更新 更多