SELECT *
FROM reservation
WHERE id NOT IN (select reservation_id
FROM reservation_log
WHERE change_type = 'cancel')
O:
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 primera versión es más intuitiva, pero creo que la segunda suele tener un mejor rendimiento (suponiendo que tenga índices en las columnas utilizadas en la combinación).
La segunda versión funciona porque LEFT JOIN
devuelve una fila para todas las filas de la primera tabla. Cuando el ON
la condición tiene éxito, esas filas incluirán las columnas de la segunda tabla, al igual que INNER JOIN
. Cuando la condición falla, la fila devuelta contendrá NULL
para todas las columnas de la segunda tabla. El WHERE l.id IS NULL
test luego hace coincidir esas filas, por lo que encuentra todas las filas que no tienen una coincidencia entre las tablas.