2010-12-16 13 views

Odpowiedz

44

Aby zapisać normalnych godzin eksploatacji, trzeba by zapisać liczbę rekordów zawierających:

  • Shop - INTEGER
  • DzienTygodnia - INTEGER (0-6)
  • OpenTime - CZAS
  • CloseTim e - TIME

zakładam na przykład, że każdy sklep skrócenie czasu podczas świąt narodowych lub ma przestojów roślin, więc trzeba także przechowywać niektóre zapisy ręczne:

  • sklep - Integer
  • OverrideStartDate - DATA
  • OverrideEndDate - DATA
  • DzienTygodnia - INTEGER (0-6)
  • AltOpenTime - TIME
  • AltCloseTime - TIME
  • Zamknięty - INTEGER (0, 1)

Aby znaleźć otwarte sklepów jest trywialne, ale trzeba także sprawdzić, czy istnieją godzin ręczne:

SELECT Shop 
FROM OverrideHours 
WHERE OverrideStartDate <= NOW() 
AND OverrideEndDate >= NOW() 
AND DayOfWeek = WEEKDAY(NOW()) 

Jeśli istnieje są wszelkie rekordy zwrócone, te sklepy mają alternatywne godziny lub są zamknięte.

Może być trochę fajnego SQL-fu, który możesz tutaj zrobić, ale to daje podstawy.

EDIT

Nie testowałem tego, ale to powinno się zamknąć:

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

EDIT

Jeśli chodzi o wydajność, to jest skuteczne w tym sensie, że musisz tylko wykonać jedno połączenie z MySQL, które często jest wąskim gardłem, jeśli jest w sieci. Będziesz musiał sprawdzić i sprawdzić, czy spełnia on twoje wymagania. Jeśli nie, możesz grać z niektórymi indeksami.

EDIT

Testing. Niezupełne testy, ale niektóre.

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

Świetna odpowiedź! Szybkie pytanie: Czy wskazane byłoby umieszczanie indeksów w 'Shop',' DayOfWeek', 'OpenTime' ORAZ' CloseTime'? – RabidFire

+1

@RabidFire, zobacz odpowiedzi na http://stackoverflow.com/questions/3049283/mysql-indexes-what-are-the-best-practises. Jeśli podstawowa wydajność, której szukasz, to zapytanie (na przykład w przeciwieństwie do wstawiania), dodanie indeksu do dowolnego pola użytego w WHERE lub JOIN ON powinno przyspieszyć wyszukiwanie.Będziesz musiał sprawdzić, które z nich są najbardziej skuteczne. –

+0

@RobertGowland A co, jeśli nocny bussinsess otworzy się o 17:00 i zamknie o 3 rano następnego dnia? – Antoniossss

8

Rozważmy, że wszystkie godziny otwarcia są takie same co tydzień. Więc co z poniższej tabeli:

  • shop_id - INTEGER (lub dowolnym unikalnym identyfikatorem sklepu)
  • WEEK_DAY - INTEGER (0 = poniedziałek - 6 = niedziela)
  • opens_at - TIME (użyj strefę czasową)
  • closes_at - TIME (użyj strefę czasową)

Zrób stół dla sklepów wskazanych przez shop_id a następnie włóż godziny otwarcia, tj:

  • 1, 0, 08:00, 17:00
  • ...
  • 1, 5, 08:00, 12:00
  • 2, 0, 07:30, 12:30
  • 2, 0, 13:30, 17:30
  • 2, 1, 7:30, 12:30
  • 2, 1, 13:30, 17:30
  • ...

a następnie wybierz:

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