SELECT *
FROM reservation
WHERE id NOT IN (select reservation_id
FROM reservation_log
WHERE change_type = 'cancel')
OU :
SELECT r.*
FROM reservation r
LEFT JOIN reservation_log l ON r.id = l.reservation_id AND l.change_type = 'cancel'
WHERE l.id IS NULL
La première version est plus intuitive, mais je pense que la deuxième version obtient généralement de meilleures performances (en supposant que vous ayez des index sur les colonnes utilisées dans la jointure).
La seconde version fonctionne car LEFT JOIN
renvoie une ligne pour toutes les lignes de la première table. Lorsque le ON
condition réussit, ces lignes incluront les colonnes de la deuxième table, tout comme INNER JOIN
. Lorsque la condition échoue, la ligne renvoyée contiendra NULL
pour toutes les colonnes du deuxième tableau. Le WHERE l.id IS NULL
test correspond ensuite à ces lignes, de sorte qu'il trouve toutes les lignes qui n'ont pas de correspondance entre les tables.