【发布时间】:2012-10-20 13:41:40
【问题描述】:
我有一张如下表:
CREATE TABLE `zonetimes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`zone_id` int(10) unsigned NOT NULL,
`active_from_day` tinyint(1) unsigned NOT NULL DEFAULT '2',
`active_to_day` tinyint(1) unsigned NOT NULL DEFAULT '2',
`active_from` time NOT NULL,
`active_to` time NOT NULL
PRIMARY KEY (`id`)
) ENGINE=MyISAM ;
因此,用户可以添加从特定日期和时间开始到特定日期和时间结束的时间条目,例如: 周一 08:00 至周五 18:00 之间或周四 15:00 至周二 15:00 之间(注意周末的交叉点)。
我需要查询这些数据并确定一个区域当前是否处于活动状态(NOW()、DAYOFWEEK() 等)...这变得非常棘手。
如果我没有重叠,例如:从“周三晚上 8 点到周二凌晨 4 点”或从“周四下午 4 点到周二下午 4 点”,使用 BETWEEN 会很容易。
另外,需要允许用户添加整个星期,例如:星期一早上 8 点 - 星期一早上 8 点(这应该很容易,例如:where (active_from_day=active_to_day AND active_from=active_to) OR ..
有什么想法吗?
注意:我在这里Timespan - Check for weekday and time of day in mysql 发现了一个类似的问题,但没有得到答案。其中一个建议是将每一天存储为单独的行。不过,我更愿意将一个时间跨度存储多天。
更新
Terje D 下面的查询完美运行。一些测试场景:
+---------------------+-----------------+---------------+-------------+-----------+------------+
| NOW( ) | active_from_day | active_to_day | active_from | active_to | active_now |
+---------------------+-----------------+---------------+-------------+-----------+------------+
| 2012-10-31 23:41:55 | 1 | 4 | 08:00:00 | 23:40:00 | 0 |
| 2012-10-31 23:42:25 | 1 | 4 | 08:00:00 | 23:45:00 | 1 |
| 2012-10-31 23:42:57 | 4 | 1 | 08:00:00 | 09:45:00 | 1 |
| 2012-10-31 23:43:36 | 4 | 4 | 23:00:00 | 09:45:00 | 1 |
| 2012-10-31 23:44:10 | 5 | 4 | 00:00:00 | 23:44:00 | 0 |
| 2012-10-31 23:44:27 | 5 | 4 | 00:00:00 | 23:45:00 | 1 |
| 2012-10-31 23:45:14 | 2 | 2 | 00:00:00 | 00:00:00 | 0 |
上面的结果是通过运行 Terje 的查询几次生成的:
SELECT NOW( ) , active_from_day, active_to_day, active_from, active_to, (
DAYOFWEEK( NOW( ) ) > active_from_day
OR DAYOFWEEK( NOW( ) ) = active_from_day
AND TIME( NOW( ) ) > active_from
)
AND (
DAYOFWEEK( NOW( ) ) < active_to_day
OR DAYOFWEEK( NOW( ) ) = active_to_day
AND TIME( NOW( ) ) < active_to
)
OR (
active_from_day > active_to_day
OR active_from_day = active_to_day
AND active_from > active_to
)
AND (
(
DAYOFWEEK( NOW( ) ) > active_from_day
OR DAYOFWEEK( NOW( ) ) = active_from_day
AND TIME( NOW( ) ) > active_from
)
OR (
DAYOFWEEK( NOW( ) ) < active_to_day
OR DAYOFWEEK( NOW( ) ) = active_to_day
AND TIME( NOW( ) ) < active_to
)
) AS active_now FROM zonetimes
【问题讨论】:
-
仅以分钟为单位记录开始日期/时间和时间段并不容易,例如active_from_day = 2, active_from = 15:00, period = 10080(1 整周)
-
我喜欢你的目标。如果开始日期/时间在星期五,时间跨度为 5 天,我们在星期一查询,这仍然有点棘手。类似于 UNIX_TIMESTAMP()/60 BETWEEN ({start} AND {start}+period)。所以只需要使用某种形式的日期函数来创建 {start} 。我试试看