2012-02-20 14 views
20

Mis mesas están dispuestas algo como esto:Comprobación de si un elemento no existe en otra mesa

table name: process 
fields: name, id_string 

table name: value_seach 
fields: id_string, value 

Quiero construir una instrucción de selección que mostrará todos los nombres de procesos (con su respectiva ID_STRING) que no tienen una entrada en value_search.

id_string en la tabla de proceso puede ser null, y aún tener un nombre, pero estos deben excluirse si es posible. La id_string en value_search nunca puede ser nulo

¿Cómo puedo hacer esto?

+0

El operador relacional que necesita es semi difference a.k.a. anti join. – onedaywhen

Respuesta

33

En general, si quieres filas que no existen en otra mesa, luego a la izquierda unirse a la otra mesa y DONDE .. . IS NULL a una columna en la segunda tabla. También mencionó que no quiere filas donde process.id_string es NULL.

SELECT p.name, p.id_string 
FROM 
    process p 
    LEFT JOIN value_search v 
     ON v.id_string = p.id_string 
WHERE 
    v.id_string IS NULL 
    AND p.id_string IS NOT NULL 

Esto se conoce como anti-join.

+0

Esto fue muy útil. Gracias. – 1man

2
SELECT 
    name, 
    id_string 
FROM process 
WHERE id_string IS NOT NULL AND id_string NOT IN SELECT id_string FROM value_seach 
+0

Esto funcionará, pero será mucho más lento que una combinación externa. –

+0

acepta que tu respuesta es mejor – alexsuslin

4

La consulta que desea debe verse más o menos así. Tenga en cuenta que un JOIN será significativamente más rápido que una subconsulta en la cláusula WHERE.

SELECT p.name, p.id_string 
FROM process p 
LEFT OUTER JOIN value_search v 
    ON p.id_string = v.id_string 
    AND p.id_string IS NOT NULL 
    AND v.id_string IS NULL 

Una variante igualmente válida de la consulta anterior sería:

SELECT p.name, p.id_string 
FROM process p 
LEFT OUTER JOIN value_search v 
    ON p.id_string = v.id_string 
WHERE 
    p.id_string IS NOT NULL 
    AND v.id_string IS NULL 
24

Creo que usar Not Exists sería su mejor opción aquí.

SELECT p.name, p.id_string 
FROM process p 
WHERE 
    NOT p.id_string IS NULL AND 
    NOT EXISTS(
      SELECT NULL 
      FROM value_search v 
      WHERE p.id_string = v.id_string) 
+1

Esto funcionará, pero será mucho más lento que una combinación externa. –

+4

@BrianDriscoll No, 'Combinación externa izquierda' con 'verificación nula' y 'No existente' creará el mismo plan de consulta incluso si la tabla izquierda tiene valores nulos o no. Consulte: http://explainextended.com/2009/09/17/not-in-vs-not-exists-vs-left-join-is-null-oracle/ para obtener más información. I los valores están garantizados como 'not null',' Left join', 'Not exists' y' Not in' crearán el mismo plan de consulta. – Magnus

+4

@BrianDriscoll También tenga en cuenta que para muchos otros DBMS, como el servidor SQL, un 'Left Outer Join' con verificación' NULL' daría el peor rendimiento ya que no puede discernir un ANTI JOIN. – Magnus

Cuestiones relacionadas