JOINステートメントで、かなり単純なクエリとサブクエリを組み合わせています。サブクエリの選択に*を含めた場合にのみ機能します。どうして?
これは機能します
$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';
これはしません
$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';
私はそれをこのようにすべきですか?すべてのフィールドが必要ない場合、*は最適ではないと思いましたか?
これを試してください(あなたの意図が正しく理解されていれば、nullではなくtype_idでフィルタリングしたかった):
$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';
説明は、外部クエリで参照されているすべてのフィールドを内部クエリで選択する必要があることです。
Type_idにNULL以外の値を設定したいので、LEFT JOINを使用しないでください。標準のJOINを使用する次のものが必要です。
$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';
JOINの要点は、実際に存在する行のみを結合することです。したがって、location_hoursにlocation.idに対応するlocation_idがない行は取得されません。次に、location_hours.type_idのNULL値を除外します。