2013-08-21 10 views
5

Mam 2 tabele, restauracje i zamówienia, tabele zamówień mają restaurant_id, status i date pól, każdy dzień jest oddzielną linią w tabeli zamówień.lewy dołączyć z co najmniej jednym wierszem z warunkiem od prawej mysql

Muszę odfiltrowywać restauracje i pokazywać tylko restauracje, które mają co najmniej jedną rezerwację w pewnym zakresie dat, ale muszę pokazać ją w kalendarzu, powinna ona wyglądać jak lista restauracji z informacjami.

czymś jak to

enter image description here

So, oznacza to, że jeśli at least one day with reserved status warunek jest spełniony w tym przedziale czasowym, wszystkie zamówienia dla tego zakresu dat dla tej restauracji powinny być pobierane również.

nie mogę zrobić zwykły sprzężenia wewnętrznego,

SELECT r.`id`, r.`name`, o.`date`, o.`status` 
FROM restaurants r 
INNER JOIN orders o ON r.id = o.restaurant_id AND o.date BETWEEN '2013-08-10' AND '2013-08-31' 
AND status = 'reserved' 

, ponieważ w tym przypadku, na przykład, nie będę miał informacji o zamówieniu na 31 sierpnia, na restaurant2, bo choć jest w data wściekłości od 10 do 31, ale jego status jest "zamknięty". Tak, myślę, aby lewy przyłączyć się ten

SELECT r.`id`, r.`name`, o.`date`, o.`status`, o.`id` order_id 
FROM restaurants r 
LEFT JOIN orders o ON r.id = o.restaurant_id AND 
o.date BETWEEN '2013-08-10' AND '2013-08-31' 
WHERE o.`id` IS NOT NULL 

Ale muszę też dodać jeden warunek, aby upewnić się, że istnieje co najmniej jeden wiersz o statusie zlecenia = „zarezerwowana”, starałem się dodać gdzie klauzula taka jak COUNT(o.status = 1) > 0, ale powoduje błąd.

THanks

+1

Użyj podkwerenda uzyskać restauants z co najmniej jednego rekordu, gdzie stan jest zarezerwowanym Wtedy y. możesz użyć wewnętrznego sprzężenia. –

+0

@DanBracuk Czy możesz trochę o tym powiedzieć? Dzięki – dav

Odpowiedz

3

Myślę, że najlepszym sposobem osiągnięcia tego celu (zakładając, że takie rzeczy jak „N/A” i „zastrzeżone” są przechowywane w zleceniach stół jest dołączenie do wszystkich zleceń w pierwszej kolejności, a następnie użyć drugi łączą się ograniczać go tylko do restauracji, które mają rezerwacji w tym okresie:

SELECT r.`id`, r.`name`, o.`date`, o.`status`, o.`id` order_id 
FROM restaurants r 
     INNER JOIN orders o 
      ON r.id = o.restaurant_id 
      AND o.date BETWEEN '2013-08-10' AND '2013-08-31' 
     INNER JOIN 
     ( SELECT DISTINCT o2.Restaurant_ID 
      FROM orders o2 
      WHERE o2.date BETWEEN '2013-08-10' AND '2013-08-31' 
      AND  o2.Status = 'Reserved' 
     ) o2 
      ON r.id = o2.restaurant_id; 

Example on SQL Fiddle

+0

nie masz pojęcia, ile jestem wdzięczny :). Wielkie dzięki. A lemme zapytaj o jedną rzecz - czy będzie to bardzo drogie, jeśli mam setki tysięcy restauracji? Jakie indeksy będę potrzebował, aby ją zoptymalizować? – dav

+0

Tak, jest to prawdopodobnie najbardziej skalowalne rozwiązanie. Nie wiem, jakie inne zapytania możesz użyć w tabelach, ale do tego mam albo 3 indeksy na 'zamówieniach' na' restaurant_id', 'status' i' date', albo w zależności od twojej dystrybucji może lepiej mają tylko dwa indeksy, z których jeden znajduje się na dwóch kolumnach, trudno powiedzieć dokładnie, nie znając rozkładu danych. na przykład Jeśli każde 'zamówienie' jest niepowtarzalne w restauracji na dzień, dodałem unikalny indeks do tych dwóch kolumn, z pojedynczym nieklastrowanym indeksem statusu. – GarethD

+0

Bardzo dziękuję za pomoc. Chciałem zapytać o jeszcze jedną rzecz. Próbowałem użyć tego samego zapytania, ale z lewym złączeniem (anti-join) w celu uzyskania darmowych restaruantów, ale nie mogłem tego rozgryźć, gdybyś mi pomógł, to byłoby wspaniale - napisałem nowe pytanie dla tego http://stackoverflow.com/questions/18362311/left-join-with-empty-rows-from-right-table-mysql. Dzięki – dav

Powiązane problemy