2010-12-16 58 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