Mysql 如何将查询结果限制在每天的特定时间范围内?

Mysql 如何将查询结果限制在每天的特定时间范围内?,mysql,sql,utc,Mysql,Sql,Utc,我有一个应用程序,可以显示活动中的广告。我将每个活动的广告集的显示限制在每个活动的特定日期范围内。我的“活动”表如下所示: campaigns id : integer start_date : date end_date : date SELECT ads.* FROM ads INNER JOIN campaigns ON campaigns.id = ads.campaign_id WHERE campaigns.start_date <= "2014-

我有一个应用程序,可以显示活动中的广告。我将每个活动的广告集的显示限制在每个活动的特定日期范围内。我的“活动”表如下所示:

campaigns
  id : integer
  start_date : date
  end_date : date
SELECT
  ads.*
FROM
  ads
  INNER JOIN campaigns ON campaigns.id = ads.campaign_id
WHERE
  campaigns.start_date <= "2014-08-05" AND
  campaigns.end_date >= "2014-08-05" AND
  campaigns.start_time <= "13:30"
  campaigns.end_time >= "13:30";
我现在需要能够选择性地限制每天在特定时间范围内显示竞选广告。所以现在我的桌子看起来像

campaigns
  id : integer
  start_date : date
  end_date : date
  start_time : time, default: null
  end_time : time, default: null
因此我的[MySQL]查询如下所示:

campaigns
  id : integer
  start_date : date
  end_date : date
SELECT
  ads.*
FROM
  ads
  INNER JOIN campaigns ON campaigns.id = ads.campaign_id
WHERE
  campaigns.start_date <= "2014-08-05" AND
  campaigns.end_date >= "2014-08-05" AND
  campaigns.start_time <= "13:30"
  campaigns.end_time >= "13:30";

我如何调整查询(甚至使用代码)来解释这一点?

问题比看起来更难,因为活动或比较时间跨度可能超过日期界限。然后,还有一个额外的并发症。如果活动说它一直运行到凌晨1:00,那么结束日期是当前日期还是下一个日期?换句话说,以你为例,2014-08-06的凌晨1:00应该算作2014-08-05

那么,我的建议是改用当地时间。如果你的活动没有跨越午夜,那么这应该可以解决你的问题

如果您只关心整个午夜的活动本身,您可以执行以下操作:

WHERE campaigns.start_date <= '2014-08-05' AND
      campaigns.end_date >= '2014-08-05' AND
      ((campaigns.start_time <= campaigns.end_time and
        campaigns.start_time >= '13:00' and
        campaigns.end_time <= '18:00'
       ) or
       (campaigns.start_time >= campaigns.end_time and
        (campaigns.start_time >= '13:00' or
         campaigns.end_time <= '18:00'
        )
       )
活动开始日期='2014-08-05'和
((活动开始时间='13:00'和
活动.end\u时间=活动.end\u时间和
(活动开始时间>='13:00'或

活动结束时间您只需检查两种方式即可

 SELECT
      ads.*
    FROM
      ads
      INNER JOIN campaigns ON campaigns.id = ads.campaign_id
    WHERE "2014-08-05" BETWEEN campaigns.start_date AND campaigns.end_date
      AND ("13:30" BETWEEN campaigns.start_time AND campaigns.end_time
        OR "13:30" BETWEEN campaigns.end_time AND campaigns.start_time)
如果您的范围是
08:00
16:00
,则第一部分将找到您的结果,第二部分将找不到,因为范围错误


如果您的范围是从
16:00
08:00
,第一部分将找不到任何结果,第二部分将为您提供结果。

因此,Gordon Linoff的回答给了我正确的方向。以下是有效的查询:

SELECT
  ads.*
FROM
  ads
  INNER JOIN campaigns ON campaigns.id = ads.campaign_id
WHERE
    "2014-08-05" BETWEEN campaigns.start_date AND campaigns.end_date AND

    (campaigns.start_time IS NULL OR campaigns.end_time IS NULL) OR (
      ((campaigns.start_time < campaigns.end_time AND
        campaigns.start_time <= "13:30:00" AND campaigns.end_time >= "13:30:00") OR

       (campaigns.start_time > campaigns.end_time AND
        ((campaigns.start_time <= "13:30:00" AND campaigns.end_time <= "13:30:00") OR
         (campaigns.start_time >= "13:30:00" AND campaigns.end_time >= "13:30:00"))))
    );
选择
广告*
从…起
广告
campaigns.id=ads.campaign\u id上的内部加入活动
哪里
活动开始日期和活动结束日期之间的“2014-08-05”
(campaigns.start_time为空或campaigns.end_time为空)或(
((活动开始时间<活动结束时间和
活动。开始时间=“13:30:00”)或
(campaigns.start_time>campaigns.end_time和
((campaiments.start_time=“13:30:00”))
);

日期时间可以是一个单独的列吗?开始时间和结束时间来自哪里?-意思是UTC和CDT是如何产生的?比较或不同的时区来自哪里from@Strawberry不,我需要每天的时间。把开始日期和开始时间放在一起意味着活动应该在某个特定的日期和时间开始时间而不是日期范围内的每天。@John Ruddell抱歉,我打错了。应该在查询中插入当前时间。它是固定的。将转换_tz()这里有一个合理的选择吗?@JohnRuddell…是和否。我认为,问题是数据库以UTC格式存储日期,但业务要求是日历日期,大概在中央时区。这是一个根本性的问题,因为日期部分没有对齐。
convert_tz()
可能可以帮助解决这个问题。如果没有一些数据,很难判断表和参数之间的区别。。但是看看这将如何工作会很有趣。@Gordon Linoff您的解决方案的一个变体工作了!非常感谢。我会在这里发布一个解释的答案,但我会感谢您。