2010-12-16 61 views

回答

44

要存储的正常运行时间,你将需要存储多个含有记录:

  • 店 - INTEGER
  • DAYOFWEEK - INTEGER( 0-6)
  • OpenTime - TIME
  • CloseTim Ë - TIME

我假设例如在节假日每家店铺已经减少小时,或有工厂停工,所以你也需要存储一些替代记录:

  • 店 - INTEGER
  • OverrideStartDate - DATE
  • OverrideEndDate - DATE
  • DAYOFWEEK - INTEGER(0-6)
  • AltOpenTime - TIME
  • AltCloseTime - TIME
  • 封闭 - 整数(0,1)

找到空位的商店是微不足道的,但你还需要检查是否有越权小时:

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) 
+0

很好的回答!快速提问:建议在“Shop”,“DayOfWeek”,“OpenTime”和“CloseTime”上添加索引吗? – RabidFire 2010-12-31 06:26:13

+1

@RabidFire,请参阅http://stackoverflow.com/questions/3049283/mysql-indexes-what-are-the-best-practises的答案。如果您要查找的主要效率是查询(而不是插入),那么向WHERE或JOIN ON中使用的任何字段添加索引应加快搜索速度。你必须测试一下,看哪一个是最有效的。 – 2011-01-04 17:35:20

+0

@RobertGowland如果晚上bussinsess在下午5点开门,第二天凌晨3点关门呢? – Antoniossss 2017-09-08 11:08:19

8

让我们考虑每周的开放时间都是一样的。那么,关于下表:

  • shop_id - INTEGER(或车间的任何唯一标识符)
  • WEEK_DAY - INTEGER(0 =周一 - 6 =周日)
  • opens_at - 时间(使用本地时区)
  • closes_at - 时间(使用本地时区)

做一个表,通过shop_id标识的商店,然后插入的开放时间,即:

  • 1,0,8点,17:00
  • ...
  • 1,5,8点,12:00
  • 2,0:30,7:30,12:30
  • 2,0,13:30,17:30
  • 2,1:30,7:30,12:30
  • 2,1,13:30,17:30
  • ...

,然后选择:

SELECT shop_id 
FROM opening_hours 
WHERE WEEKDAY(NOW()) = week_day 
AND TIME(NOW()) BETWEEN opens_at AND closes_at