【问题标题】:Storing Time Ranges in MySQL and Determine if Current Time is within Time Range在 MySQL 中存储时间范围并确定当前时间是否在时间范围内
【发布时间】:2011-09-08 10:28:08
【问题描述】:

我有一个数据库表,将商店的营业时间存储为 TIME 格式的时间范围。例如,如果商店的营业时间是“上午 9 点至下午 5 点”,则将有 2 列“hours_open”和“hours_close”,其中我将 9:00 存储在“hours_open”中,17:00 存储在“hours_close”中。要确定商店当前是开门还是关门,我将运行查询:

SELECT * 
  FROM shop 
 WHERE CAST(NOW() AS TIME) BETWEEN hours_open AND hours_close;

我现在需要做的是容纳营业时间超过午夜的商店,例如晚上 9 点到凌晨 3 点。此外,商店在不同的日子可能有不同的营业时间,例如:周一至周四:晚上 9 点至凌晨 3 点,周五至周日:晚上 9 点至凌晨 5 点。

现在我被难住了。我应该如何进行?我每天可以有一对“hours_open”和“hours_close”,例如:“mon_hours_open”、“mon_hours_close”、“tue_hours_open”、“tue_hours_close”……

但是我该如何处理超过午夜的营业时间,例如晚上 9 点到凌晨 5 点?

有什么见解吗?如果有帮助,我正在使用 PHP 和 Codeigniter 框架。

【问题讨论】:

    标签: php mysql sql codeigniter time


    【解决方案1】:

    在以下方面有很好的想法:给定的预订期是否可用?
    (http://www.artfulsoftware.com/infotree/queries.php#576)。 它在类似的情况下帮助了我。

    【讨论】:

    • provide context for links。直接在你的答案中总结要点;包含该链接仅作为参考、致谢或更多信息。至少在您的答案中直接包含一些示例代码。
    【解决方案2】:

    如果将小时数存储在单独的表中会更容易检查,例如

    shop_working_hours ( shop_id int FK, day_of_week int, hours_open 时间, 小时关闭时间, PK(shop_id,day_of_week) )

    这样查询可能是这样的:

    SELECT s.*
    FROM shop s
      INNER JOIN shop_working_hours h ON s.id = h.shop_id
    WHERE
      CASE
        WHEN h.hours_close > h.hours_open THEN
          h.day_of_week = DAYOFWEEK(NOW()) AND
          CAST(NOW() AS time) >= h.hours_open AND CAST(NOW() AS time) < h.hours_close
        ELSE
          h.day_of_week = DAYOFWEEK(NOW() - 1) AND
          CAST(NOW() AS time) >= h.hours_open OR CAST(NOW() AS time) < h.hours_close
      END
    

    但是,如果您更愿意在同一个表(即shop 表)中每周的每一天使用多个列,例如 *_hours_open*_hours_close,那么过滤条件很可能必须是更复杂,可能是这样的:

    SELECT s.*
    FROM shop s
      CROSS JOIN (
        SELECT 1 AS day_of_week
        UNION ALL SELECT 2
        UNION ALL SELECT 3
        UNION ALL SELECT 4
        UNION ALL SELECT 5
        UNION ALL SELECT 6
        UNION ALL SELECT 7
      ) h
    WHERE
      CASE h.day_of_week
        WHEN 1 THEN
          CASE
            WHEN s.mon_hours_close > s.mon_hours_open THEN
              h.day_of_week = DAYOFWEEK(NOW()) AND
              CAST(NOW() AS time) >= s.mon_hours_open AND
              CAST(NOW() AS time) < s.mon_hours_close
            ELSE
              h.day_of_week = DAYOFWEEK(NOW() - INTERVAL 1 DAY) AND
              CAST(NOW() AS time) >= s.mon_hours_open OR
              CAST(NOW() AS time) < s.mon_hours_close
          END
        WHEN 2 THEN
          CASE
            WHEN s.tue_hours_close > s.tue_hours_open THEN
            …  /* same for Tuesday */
          END
        …  /* and for all the other days of week */
      END
    

    【讨论】:

    • 很棒的代码,当我试图弄清楚代码是如何工作的时,我想知道这是否会考虑到一周中的不同日子,因为我没有看到对日子的引用
    • @Nyxynyx:哎呀,好像我错过了那一点。我会在大约半小时内审查我的答案(我想)。
    • 例如,商店的营业时间为周一晚上 9 点至周二凌晨 3 点,周二晚上 9 点至周三凌晨 3 点。在这种情况下,hours_open_mon = 2100,hours_close_mon = 0300,hours_open_tue = 2100,hours_close_tue = 0300。如果现在时间是星期一晚上 11 点,我们进入 ELSE 分店,商店被视为营业。如果现在时间是星期二凌晨 1 点,则没有代码告诉它我们仍然应该将 NOW() 与 hours_close_mon 进行比较,而不是 hours_close_tue
    • 太好了,让它与其他条件语句很好地配合,使其更精确和通用:)
    【解决方案3】:

    opening 表中可以有三个字段:

    opening
        day_opens       <--- what day the shop opens
        hour_opens      <--- what hour the shop opens
        duration_open   <--- how many hours it stays open
    

    所以检查它现在是否开放(或在特定的日期和时间),它会是这样的条件:

    WHERE (   day_opens = Day(NOW()) 
          AND hourOpens <= Hour(NOW())
          AND Hour(NOW()) < hourOpens + duration_open 
          )
       OR (   day_opens + 1 = Day(NOW())
          AND Hour(NOW()) < hourOpens + duration_open - 24
          )
    

    在一种情况下甚至更好:

    WHERE day_opens * 24 + hourOpens    <= Day(NOW()) * 24 + Hour(NOW())
      AND Day(NOW()) * 24 + Hour(NOW()) <  day_opens * 24 + hourOpens + hourOpens
    

    【讨论】:

    • 我没有将代码说明不同日期的不同营业时间。如果商店每天的营业时间相同,上面的代码似乎很适合商店。但我从你的方法中学到了很多东西!
    【解决方案4】:

    这样的日子在您的工作表中有两个条目怎么样,一个是星期一 09:00:00 - 11:59:59,另一个是星期二 12:00:00 - 03:00:00?

    【讨论】:

    • 我想知道这是否会再创建 14 列(7 天 x 2)并降低性能?
    • 它会创建更多的行,而不是更多的列。 14排和7排的差别真的不是很大。在性能成为问题之前,我不会太担心性能的微优化。从这样的表中选择一行应该是微不足道的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 2012-11-22
    • 1970-01-01
    相关资源
    最近更新 更多