2013-08-21 13 views
5

Ho 2 tavoli, i ristoranti e gli ordini, tabella degli ordini hanno restaurant_id, status e date campi, ogni giorno è una riga separata nella tabella degli ordini.LEFT JOIN con almeno una fila con condizioni da mysql destra

Devo filtrare i ristoranti e mostrare solo i ristoranti che hanno almeno una prenotazione per un intervallo di date, ma devo mostrarlo su un calendario, dovrebbe apparire come un elenco di ristoranti con informazioni.

Smth come questo

enter image description here

Quindi, vuol dire che se at least one day with reserved status condizione è soddisfatta in quel intervallo di date, tutti gli ordini per quella intervallo di date per quel ristorante dovrebbero essere prelevati pure.

non riesco a fare partecipare a una consueta interna,

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' 

perché, in questo caso, per esempio, io non ho le informazioni di ordine per il 31 agosto, in occasione restaurant2, perché anche se è data la rabbia da 10 a 31, ma il suo stato è 'chiuso'. Quindi, sto pensando di fare un left join come questo

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 

ma ho bisogno di aggiungere anche una condizione per assicurare che ci sia almeno una riga con lo stato di ordine = 'riservato', ho provato ad aggiungere dove clausola come COUNT(o.status = 1) > 0 ma dà un errore.

THanks

+1

Utilizzare una sottoquery per ottenere i insipido con almeno un record in cui lo stato è riservato allora Y. Puoi usare un'unione interna. –

+0

@DanBracuk Potresti espanderne un po '? Grazie – dav

risposta

3

Penso che il modo migliore per raggiungere questo (supponendo che le cose come 'N/A' e 'riservato' sono memorizzati negli ordini tavolo è quello di unire a tutti gli ordini in prima istanza, e quindi utilizzare un secondo iscriverti per limitarlo ai soli ristoranti che hanno una prenotazione entro tale termine:

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

non hai idea di quanto ti ringrazio :). Molte grazie. E lasciami chiedere una cosa: sarà molto costoso se avrò centinaia di migliaia di ristoranti? E di quali indici avrò bisogno per ottimizzarlo? – dav

+0

Sì, questa è probabilmente la soluzione più scalabile. Non so quali altre query potresti usare sulle tabelle, ma per questo avrei 3 indici su 'orders' su' restaurant_id', 'status' e' date', oppure a seconda della tua distribuzione potrebbe essere meglio hanno solo 2 indici, con uno di loro su due colonne, difficile da dire esattamente senza conoscere la distribuzione dei dati. per esempio. Se ogni "ordine" è univoco per ristorante al giorno, aggiungerei un indice univoco su queste due colonne, con un singolo indice non cluster sullo stato. – GarethD

+0

Grazie davvero per il tuo aiuto. Volevo chiedere ancora una cosa. Ho provato a usare la stessa query ma con join sinistro (anti-join) per ottenere i restaruants liberi, ma non riuscivo a capirlo, se potessi aiutarmi con esso, sarebbe fantastico - Ho postato una nuova domanda per questo http://stackoverflow.com/questions/18362311/left-join-with-empty-rows-from-right-table-mysql. Grazie – dav