Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SQL] Wyświetlanie wolnych pokoi wg. terminarza
Forum PHP.pl > Forum > Przedszkole
coCCine
Cześć wszystkim!

Zastanawiam się w jaki sposób OPTYMALNIE zrealizować następujące założenie. Mamy tabelę gdzie trzymam spis pokoi, oraz tabele, w której trzymam informacje
nt. rezerwacji dla danego pokoju. Użytkownik przez formularz wysyła dwie daty (startową i końcową - od kiedy; do kiedy chce wynająć pokój) i teraz chciałbym pobrać listę pokoi (nazwa pokoju, opis pokoju, itd), gdzie rezerwacja będzie wolna - myślałem nad takim rozwiązaniem;

  1. # {CZAS_START} - unixtimestamp (np. 2013-10-01)
  2. # {KONIEC_CZASU} - unixtimestamp (np. 2013-10-08)
  3.  
  4. SELECT p.id AS pokoj_id, p.name, p.description FROM pokoje AS p
  5. WHERE p.id NOT IN(SELECT rez.hotel_pokoj_id FROM rezerwacje AS rez WHERE raz.start_rezerwacji >= {CZAS_START} AND raz.koniec_rezerwacji <= {KONIEC_CZASU})
  6. AND p.country_id = 'pl'


Struktura tabel wygląda mniej więcej tak:
  1. # pokoje
  2. id, name, description, country_id
  3.  
  4. # rezerwacje
  5. id, hotel_pokoj_id, start_rezerwacji, koniec_rezerwacji, dane_kontaktowe


Chciałbym Was prosić, czy dobrze jest zbudowana LOGIKA tego podzapytania - czy warunek WHERE ma sens ?
mmmmmmm
Wszystko zależy od DBMS. MySQL średnio sobie poradzi z IN. Dla postgeSQL nie będzie to żadnym problemem.
Niemniej, ja bym to przerobił na inne zapytanie:
  1. SELECT p.id AS pokoj_id, p.name, p.description FROM pokoje AS p LEFT JOIN rezerwacje AS rez ON p.id=rez.hotel_pokoj_id AND rez.start_rezerwacji >= {CZAS_START} AND rez.koniec_rezerwacji <= {KONIEC_CZASU}
  2. WHERE p.country_id = 'pl' AND rez.hotel_pokoj_id IS NULL

Poza tym chyba masz parametry CZAS_START i KONIEC_CZASU na odwrót. Załóżmy taką sytuację:
CZAS_START: '2013-10-01'
KONIEC_CZASU: '2013-10-10'
rezerwacje:
1 '2013-10-01' '2013-10-07'
2 '2013-09-30' '2013-10-05'
3 '2013-09-30' '2013-10-12'
4 '2013-10-09' '2013-10-15'
Wg twojego zapytania tylko pokoj 1 'się załapie' jako zajęty. A tak nie jest - każdy z nich jest zajęty w tym okresie (choć w części). Zamień WHERE na rez.start_rezerwacji >= {KONIEC_CZASU} AND rez.koniec_rezerwacji <= {CZAS_START} i zobacz, co się stanie... smile.gif
Sephirus
Nie wchodząc w sprawy techniczne a algorytmiczne:

Jeśli mamy dwa zakresy dat, które nie mogą się w żaden sposób krzyżować to musisz sprawdzić sporo możliwych kombinacji.

Jeśli data startu planowanej rezerwacji zawiera się w okresie zajętości pokoju
lub
jeśli data końca planowanej rezerwacji zawiera się w okresie zajętości pokoju
lub
jeśli data startu zajętości pokoju zawiera się w okresie planowanej rezerwacji
lub
jeśli data końca zajętości pokoju zawiera się w okresie planowanej rezerwacji

to ten pokój powinien zostać wyeliminowany. Wystarczy to zanegować i użyć w zapytaniu by otrzymać listę pokoju które mogą być zarezerwowane smile.gif

  1.  
  2. NOT (
  3. rez.start_rezerwacji BETWEEN {CZAS_START} AND {KONIEC_CZASU}
  4. OR
  5. rez.koniec_rezerwacji BETWEEN {CZAS_START} AND {KONIEC_CZASU}
  6. OR
  7. {CZAS_START} BETWEENrez.start_rezerwacji AND rez.koniec_rezerwacji
  8. OR
  9. {KONIEC_CZASU} BETWEENrez.start_rezerwacji AND rez.koniec_rezerwacji
  10. )
  11.  
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.