我打算存储商店的工作时间。我想知道在工作时间字段中最好的建模方法是什么,这样我就可以以非常有效的方式获得当前时刻开/关商店的列表。
要存储正常的工作时间,您需要存储一些记录,其中包含:
例如,我假设每个商店在国定假日减少工作时间或关闭工厂,因此您还需要存储一些替代记录:
要找到开放式商店并不容易,但是您还需要检查是否有超车时间:
SELECT Shop FROM OverrideHours WHERE OverrideStartDate <= NOW() AND OverrideEndDate >= NOW() AND DayOfWeek = WEEKDAY(NOW())
如果返回任何记录,则这些商店将有其他时间或关闭。
您可以在此处执行一些不错的SQL-fu,但这为您提供了基础知识。
编辑
我还没有测试过,但这应该可以使您接近:
SELECT Normal.Shop FROM Normal LEFT JOIN Override ON Normal.Shop = Override.Shop AND Normal.DayOfWeek = Override.DayOfWeek AND NOW() BETWEEN Override.OverrideStartDate AND Override.OverrideEndDate WHERE Normal.DayOfWeek = WEEKDAY(NOW()) AND ((Override.Shop IS NULL AND TIME(NOW()) BETWEEN Normal.OpenTime AND Normal.CloseTime) OR (Override.Shop IS NOT NULL AND Override.Closed <> 1 AND TIME(NOW()) BETWEEN Override.AltOpenTime AND Override.AltCloseTime))
至于效率,从某种意义上讲,它是高效的,您只需要对MySQL进行一次调用,而如果它是跨网络的,则通常是瓶颈。您必须进行测试,看看它是否符合您的规格。如果没有,您可能会玩一些索引。
测试。没有完成测试,但是有些。
mysql> select * from Normal; +------+-----------+----------+-----------+ | Shop | DayOfWeek | OpenTime | CloseTime | +------+-----------+----------+-----------+ | 1 | 1 | 09:00:00 | 17:00:00 | | 1 | 5 | 09:00:00 | 16:00:00 | | 2 | 1 | 09:00:00 | 17:00:00 | | 2 | 5 | 09:00:00 | 17:00:00 | +------+-----------+----------+-----------+ 4 rows in set (0.01 sec) mysql> select * from Override; +------+-------------------+-----------------+-----------+-------------+--------------+--------+ | Shop | OverrideStartDate | OverrideEndDate | DayOfWeek | AltOpenTime | AltCloseTime | Closed | +------+-------------------+-----------------+-----------+-------------+--------------+--------+ | 2 | 2010-12-01 | 2010-12-31 | 1 | 09:00:00 | 18:00:00 | 0 | | 2 | 2010-12-01 | 2010-12-31 | 5 | 09:00:00 | 18:00:00 | 0 | | 1 | 2010-12-01 | 2010-12-31 | 1 | 09:00:00 | 17:00:00 | 1 | +------+-------------------+-----------------+-----------+-------------+--------------+--------+ 3 rows in set (0.00 sec) mysql> SET @whenever = TIMESTAMP('2010-11-23 16:05'); Query OK, 0 rows affected (0.00 sec) mysql> SELECT WEEKDAY(@whenever); +--------------------+ | WEEKDAY(@whenever) | +--------------------+ | 1 | +--------------------+ 1 row in set (0.00 sec) mysql> SELECT Normal.Shop FROM Normal LEFT JOIN Override ON Normal.Shop = Override.Shop AND Normal.DayOfWeek = Override.DayOfWeek AND @whenever BETWEEN Override.OverrideStartDate AND Override.OverrideEndDate WHERE Normal.DayOfWeek = WEEKDAY(@whenever) AND ((Override.Shop IS NULL AND TIME(@whenever) BETWEEN Normal.OpenTime AND Normal.CloseTime) OR (Override.Shop IS NOT NULL AND Override.Closed <> 1 AND TIME(@whenever) BETWEEN Override.AltOpenTime AND Override.AltCloseTime)); +------+ | Shop | +------+ | 1 | | 2 | +------+ 2 rows in set (0.00 sec) mysql> SET @whenever = TIMESTAMP('2010-11-23 17:05'); Query OK, 0 rows affected (0.00 sec) mysql> SELECT Normal.Shop FROM Normal LEFT JOIN Override ON Normal.Shop = Override.Shop AND Normal.DayOfWeek = Override.DayOfWeek AND @whenever BETWEEN Override.OverrideStartDate AND Override.OverrideEndDate WHERE Normal.DayOfWeek = WEEKDAY(@whenever) AND ((Override.Shop IS NULL AND TIME(@whenever) BETWEEN Normal.OpenTime AND Normal.CloseTime) OR (Override.Shop IS NOT NULL AND Override.Closed <> 1 AND TIME(@whenever) BETWEEN Override.AltOpenTime AND Override.AltCloseTime)); Empty set (0.01 sec) mysql> SET @whenever = TIMESTAMP('2010-12-25 16:05'); Query OK, 0 rows affected (0.00 sec) mysql> SELECT Normal.Shop FROM Normal LEFT JOIN Override ON Normal.Shop = Override.Shop AND Normal.DayOfWeek = Override.DayOfWeek AND @whenever BETWEEN Override.OverrideStartDate AND Override.OverrideEndDate WHERE Normal.DayOfWeek = WEEKDAY(@whenever) AND ((Override.Shop IS NULL AND TIME(@whenever) BETWEEN Normal.OpenTime AND Normal.CloseTime) OR (Override.Shop IS NOT NULL AND Override.Closed <> 1 AND TIME(@whenever) BETWEEN Override.AltOpenTime AND Override.AltCloseTime)); +------+ | Shop | +------+ | 2 | +------+ 1 row in set (0.00 sec) mysql> SET @whenever = TIMESTAMP('2010-11-23 17:05'); Query OK, 0 rows affected (0.00 sec) mysql> SELECT WEEKDAY(@whenever); +--------------------+ | WEEKDAY(@whenever) | +--------------------+ | 1 | +--------------------+ 1 row in set (0.00 sec) mysql> SELECT Normal.Shop FROM Normal LEFT JOIN Override ON Normal.Shop = Override.Shop AND Normal.DayOfWeek = Override.DayOfWeek AND @whenever BETWEEN Override.OverrideStartDate AND Override.OverrideEndDate WHERE Normal.DayOfWeek = WEEKDAY(@whenever) AND ((Override.Shop IS NULL AND TIME(@whenever) BETWEEN Normal.OpenTime AND Normal.CloseTime) OR (Override.Shop IS NOT NULL AND Override.Closed <> 1 AND TIME(@whenever) BETWEEN Override.AltOpenTime AND Override.AltCloseTime)); Empty set (0.00 sec)