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
NULLel 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 INes 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