2013-10-23 23 views
5

Sto mettendo insieme una query abbastanza semplice con una sottoquery nell'istruzione JOIN. Funziona solo se includo un * nella selezione sottoquery. Perché?MySQL Left Join Subquery con *

Questo funziona

$sql = 'SELECT locations.id, title, name, hours.lobby 
     FROM locations 
     LEFT JOIN states ON states.id = locations.state_id 
     LEFT JOIN (SELECT *, type_id IS NOT NULL AS lobby FROM location_hours) AS hours ON locations.id = hours.location_id 
     GROUP BY locations.id'; 

Questo non

$sql = 'SELECT locations.id, title, name, hours.lobby 
     FROM locations 
     LEFT JOIN states ON states.id = locations.state_id 
     LEFT JOIN (SELECT type_id IS NOT NULL AS lobby FROM location_hours) AS hours ON locations.id = hours.location_id 
     GROUP BY locations.id'; 

Dovrei anche essere farlo in questo modo? Pensavo che * non fosse il massimo se non avessi bisogno di tutti i campi?

risposta

20

provare questo (se ho capito bene il vostro intento, che si voleva filtrare type_id non null):

$sql = 'SELECT locations.id, title, name, hours.lobby 
     FROM locations 
     LEFT JOIN states ON states.id = locations.state_id 
     LEFT JOIN (SELECT location_id, type_id AS lobby FROM location_hours 
     WHERE type_id IS NOT NULL) AS hours ON locations.id = hours.location_id 
     GROUP BY locations.id'; 

La spiegazione è che si deve selezionare nella query interna tutti i campi che si fa riferimento nella query esterna.

+1

il tuo problema quando hai selezionato un solo campo dalla subquery era che non potevi fare l'istruzione join, perché hours.location_id non è stato fornito da una sottoquery se hai selezionato solo id_tipo. – Ashalynd

+0

Questo ha senso. E piuttosto ovvio, suppongo. Comunque questo funziona. Grazie. – MAZUMA

+0

Controlla anche se hai davvero bisogno di usare (nel secondo caso) LEFT JOIN invece di JOIN. Se non vuoi NULL type_id, allora presumo che potresti voler eseguire un JOIN (che di solito è più veloce). – Ashalynd

0

Poiché si desidera avere valori non NULL per type_id, non si dovrebbe utilizzare un SINISTRO SINISTRO per questo. Ti consigliamo quanto segue, che utilizza un JOIN standard.

$sql = 'SELECT locations.id, title, name, location_hours.type_id 
     FROM locations 
     JOIN location_hours ON location_hours.location_id = locations.id 
     LEFT JOIN states ON states.id = locations.state_id 
     WHERE location_hours.type_id IS NOT NULL 
     GROUP BY locations.id'; 

L'intero punto di un JOIN è che unisce solo le righe effettivamente esistenti. Quindi non otterrai nessuna riga dove location_hours non ha un id_destinazione corrispondente a locations.id. Quindi devi solo filtrare i valori NULL per location_hours.type_id.

+0

Se eseguo un join solo le righe di posizione. Voglio tutte le righe di posizione. Poi voglio vedere se sono state impostate delle ore per quelle località comprare guardando se c'è o meno un valore NULL. – MAZUMA

+0

Non sono sicuro di aver capito cosa intendi. Potresti riformularlo? Per inciso, il motivo per cui LEFT JOIN non funzionava è perché la sottoquery non sta selezionando location_id ma la stai usando per la condizione ON. – Chill

+0

Se eseguo un JOIN esclude le righe in cui non esistono ore type_id. Voglio ottenere tutte le righe di posizione e quindi vedere se esiste un valore per type_id per ogni posizione. Sto usando quel valore per determinare se le ore debbano essere aggiunte o modificate per quella particolare posizione. – MAZUMA