【问题标题】:MySQL Query to find record between start/end time within day of weekMySQL查询以查找一周中开始/结束时间之间的记录
【发布时间】:2018-12-30 21:16:54
【问题描述】:

我们是一个广播电台,其节目网格具有开始和结束时间、一周中的特定日期、一年中的特定星期。我们有周六至周日(周六晚上 11 点至周日凌晨 1 点)通宵播放的节目,还有周一、周二、周三安排的节目。

我们正在尝试向 MySQL 创建一个查询,以了解特定时间正在播出的节目。我们当前的查询不能做这样的事情。

我们如何构造一个或多个查询到当前表,只提供时间、星期几、一年中的星期几。是否需要更改表格以包含更多信息?谢谢。

我们已经尝试了以下表结构和 MySQL 查询。

MySQL:

CREATE TABLE `shows` (
    `id`        tinyint(4) NOT NULL,
    `name`      varchar(255) NOT NULL COMMENT 'Program Name',
    `starts`    time NOT NULL COMMENT 'Starting Time',
    `ends`      time NOT NULL COMMENT 'Ending Time',
    `duration`  smallint(6) NOT NULL COMMENT 'Length in seconds',
    `days` set('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') NOT NULL COMMENT 'Starting Day of the Week',
    `weeks`     set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53') DEFAULT NULL COMMENT 'Weeks of the Year',
    `active`     tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Active Program'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

PHP:

$time = date("H:i:s"); // current time
$dow = date("l"); // current Day of Week
$week = date("W");// current week

$query = "SELECT id, name, starts, ends, duration, days, weeks, active
          FROM shows WHERE starts < $time AND ends > $time
          AND FIND_IN_SET('$dow', days)
          AND FIND_IN_SET('$week', weeks)
          AND active = '1'";

示例数据: 演出于周六晚上 11 点开始,周日凌晨 1 点结束

{
    "id": "123",
    "name": "Overnight Show",
    "starts": "23:00:00",
    "ends": "01:00:00",
    "duration": "7200",
    "days": "Saturday",
    "weeks": "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53",
    "active": "1"
}

对于 $time = 00:12:00、$dow = Sunday、$weeks = 52 的给定输入,这将返回一个空结果集,因为节目从星期六开始。

【问题讨论】:

  • 由于您有开始时间和持续时间,因此您不需要结束时间 - 通过将持续时间添加到开始日期和开始时间来计算。这将解决午夜穿越问题。我可能会将开始日期和开始时间合并到一个时间戳列中。 dev.mysql.com/doc/refman/5.5/en/…
  • 对于您的设置变量,您应该使用FIND_IN_SET 例如FIND_IN_SET($dow, days) 而不是 days LIKE '%$dow%'

标签: php mysql datetime


【解决方案1】:

为了让您保持当前架构,您可以通过这种方式更改您的查询:

$time = date("H:i:s"); // current time
$dow = date("l"); // current day of Week
$dow_ystd = date("l", time() - 60*60*24); // day of Week of yesterday
$week = date("W");// current week

$query = "SELECT id, name, starts, ends, duration, days, weeks, active
          FROM shows WHERE

          (
            ( (ends > starts) AND (FIND_IN_SET('$dow', days)) AND (starts <= '$time') AND (ends >= '$time') )
            OR
            ( (ends <= starts) AND (FIND_IN_SET('$dow_ystd', days)) AND (ends > '$time') )
          )
        AND FIND_IN_SET('$week', weeks)
        AND active = '1'";

请注意,这不能处理超过 24 小时的节目(即跨越多天)。为了支持这种情况,您必须更深入地更改架构。

【讨论】:

  • 这看起来可能是解决方案,我会做一些进一步的测试!在 OR 之前的第一个 WHERE 子句中进行了一个小的修改,以防止有人在确切的开始时间查询节目。开始 '$time' 并结束 >= '$time'
  • @Ass3mbler 请检查我们是否在数据库表中没有星期,当天是Thursday,开始时间是10:40,结束时间是05:00。记录未显示,请查看此链接http://sqlfiddle.com/#!9/8a1fbb/13
【解决方案2】:

你的桌子有(至少)两个问题:

  • 同时具有开始时间和结束时间,但只有开始日期,表示您的节目在同一天开始和结束(在示例中,从 23 点到 1 点--在过去,或在一整周)。

  • 使用字符串列表作为值不仅效率低下(如果行数不多可以原谅),还会带来问题,例如用%2%查找第2周会匹配21222 等等。解决方法是在值的开头添加逗号 ,,在值的末尾添加其他逗号,然后搜索 %,2,%(您必须在数据中或在使用concat() 查询,否则它不会匹配第一个或最后一个值)。

实际的解决方案是添加两个表:

  • 您当前的shows,但没有startsendsdaysweeks
  • shows_schedule 带有开始时间和持续时间(不是结束时间)
  • shows_schedule_weeks 每周一排

给我一​​些时间,我会添加一个例子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多