Usa un EXISTS
expresión:
WHERE NOT EXISTS (
SELECT FROM votes v -- SELECT list can be empty
WHERE v.some_id = base_table.some_id
AND v.user_id = ?
)
La diferencia
... entre NOT EXISTS()
(Ⓔ) y NOT IN()
(Ⓘ) es doble:
-
Rendimiento
Ⓔ es generalmente más rápido. Deja de procesar la subconsulta tan pronto como se encuentra la primera coincidencia. El manual:
Por lo general, la subconsulta solo se ejecutará el tiempo suficiente para determinar si se devuelve al menos una fila, no hasta el final.
Ⓘ también puede ser optimizado por el planificador de consultas, pero en menor medida ya que
NULL
el manejo lo hace más complejo. -
Corrección
Si uno de los valores resultantes en la expresión de la subconsulta es
NULL
, el resultado de Ⓘ esNULL
, mientras que la lógica común esperaríaTRUE
- y Ⓔ devolveráTRUE
. El manual:Si todos los resultados por fila son desiguales o nulos, con al menos uno nulo, entonces el resultado de
NOT IN
es nulo.
Esencialmente, (NOT) EXISTS
es la mejor opción en la mayoría de los casos.
Ejemplo
Su consulta puede verse así:
SELECT *
FROM questions q
WHERE NOT EXISTS (
SELECT FROM votes v
WHERE v.question_id = q.id
AND v.user_id = ?
);
no unirse a votes
en la consulta base. Eso anularía el esfuerzo.
Además NOT EXISTS
y NOT IN
hay opciones de sintaxis adicionales con LEFT JOIN / IS NULL
y EXCEPT
. Ver:
- Seleccionar filas que no están presentes en otra tabla