web-dev-qa-db-fra.com

MySQL Left Join Subquery avec *

Je mets en place une requête assez simple avec une sous-requête dans l'instruction JOIN. Cela ne fonctionne que si j'inclus un * dans la sélection de sous-requête. Pourquoi?

Cela marche

$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';

Ce n'est pas

$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';

Dois-je même le faire de cette façon? Je pensais que * n'était pas le meilleur si vous n'avez pas besoin de tous les champs?

9
MAZUMA

essayez ceci (si j'ai bien compris votre intention, que vous vouliez filtrer sur 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';

L'explication est que vous devez sélectionner dans la requête interne tous les champs référencés dans la requête externe.

35
Ashalynd

Puisque vous voulez avoir des valeurs non NULL pour type_id, vous ne devriez pas utiliser du tout LEFT JOIN pour cela. Vous aurez besoin de ce qui suit, qui utilise 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'intérêt d'un JOIN est qu'il joint uniquement les lignes qui existent réellement. Ainsi, vous n'obtiendrez aucune ligne où location_hours n'a pas d'emplacement_id correspondant à locations.id. Ensuite, vous filtrez simplement les valeurs NULL pour location_hours.type_id.

0
Chill