Cómo deshacerse de NO EXISTE

Tengo un sql que no es muy complejo pero lo suficientemente confuso que cuestiono más bien tengo un equivalente o por coincidencia que el recuento sea el mismo.

SQL1:

SELECT a, b
FROM table1
WHERE NOT EXISTS(
  SELECT a, c
  FROM TABLE2
  WHERE table2.a != table1.a)

SQL2

SELECT table1.a, table1.b
FROM table1
LEFT JOIN table2 ON table2.a = table1.a
WHERE table2.a IS NULL

El recuento de los dos es idéntico, pero no estoy seguro de si esto es por casualidad, y quiero asegurarme de que la conversión no cambie la funcionalidad original.

preguntado el 09 de marzo de 12 a las 15:03

No estoy seguro de obtener la funcionalidad de SQL1. ¿Quiere obtener a, b de table1 donde a es el único valor de table2.a? -

Creo que el objetivo es obtener filas de la tabla 1 donde no hay una entrada correspondiente en la tabla 2. -

@Dave Sí, creo que ese es el propósito original. Pero no estoy 100% seguro y estoy tratando de optimizarlo para que se ejecute más rápido. -

La forma en que se escribe la primera consulta parece ser obtener todas las filas de la tabla 1 de modo que no existan filas que no coincidan en la tabla 2. Y creo que eso solo funcionaría si todos las filas de la tabla 2 coincidían exactamente uno valor de la tabla1.a -

@Churk, no mencionas qué RDBMS estás usando. Probé ambas declaraciones en Oracle y descubrí que la versión DONDE EXISTE usará un índice si hay uno en la tabla2, pero la condición de combinación con! = (Que se muestra a continuación) no lo hará. En otras palabras, está mejor con NO EXISTE, al menos en Oracle, asumiendo un índice. Sin embargo, ciertamente no necesita "SELECT a, c" en la subconsulta; simplemente puede usar "SELECCIONAR 1" o "SELECCIONAR 'X'". -

4 Respuestas

Eso no parece lo mismo, pero está cerca. Su sintaxis LEFT JOIN es la misma que:

SELECT a, b
FROM table1
WHERE NOT EXIST(
  SELECT a, c
  FROM TABLE2
  WHERE table2.a = table1.a)

Sin embargo, tenga en cuenta el "=" en lugar de "! =". ¿Estás seguro de que eso no es lo que tienes?

Su consulta real se traduce en algo como "donde no existen filas que no coincidan", lo cual sería extraño, pero podría expresarse cambiando la condición JOIN:

SELECT a, b
FROM table1
LEFT JOIN table2 ON table2.a != table1.a
WHERE table2.a IS NULL

respondido 09 mar '12, 15:03

El primer sql es lo que tengo y el segundo sql es lo que puedo cambiar. Entonces, lo que está diciendo es sobre la condición de unión, debería usar un! = en la columna de unión, pero ¿eso no causa otro problema en sí mismo? - iglesia

@Churk: El único problema que veo es que es muy confuso, pero menos que la consulta original. Es una condición extraña de verificar, y realmente no encaja bien con (al menos mi) pensamiento estándar, pero si estás 100% seguro de que eso es lo que tienes, iría con LEFT JOIN y un montón de comentarios de tipo por qué. - marca corchetes

La primera consulta, tal como la tiene, devuelve todas las filas de TABLE1 donde a coincide con todos los valores de a en la TABLA2. Por lo tanto, devolverá cero filas, a menos que haya un único valor no nulo para a en TABLA2, y ese valor existe en TABLE1. En ese caso, devolverá tantas filas como haya en TABLE1 con ese valor de a.

La segunda consulta es completamente diferente. Simplemente devolverá todas las filas de TABLE1 donde a no existe en TABLE2.

Entonces es "coincide con todos"(consulta 1) vs."no coincide con ninguno" (consulta 2). El hecho de que obtenga el mismo número de filas es pura coincidencia.

Sus consultas serían equivalentes si cambiara != para = en el primero, así:

SELECT a, b
FROM table1
WHERE NOT EXISTS(
  SELECT a, c
  FROM TABLE2
  WHERE table2.a = table1.a)

Eso te da valores de a en la tabla1 que no existe en la tabla2. Esto es EXACTAMENTE lo mismo que:

SELECT table1.a, b
FROM table1
LEFT JOIN table2 ON table2.a = table1.a
WHERE table2.a IS NULL

Sin embargo, como lo tiene, NO son equivalentes. Debes cambiar != para = en el primero para hacerlos así.

respondido 09 mar '12, 20:03

La primera consulta no puede cambiar, es de lo que estoy convirtiendo. por lo que, en orden, las dos consultas no son equivalentes, solo por coincidencia que el recuento resultó igual. - iglesia

La primera consulta no tiene una sintaxis válida (pista: EXIST), ni la segunda (pista: a en el objeto SELECT cláusula es ambigua) y tampoco son equivalentes. - un día cuando

@onedaywhen básicamente tuve que volver a escribir las consultas, así que perdona los errores de ortografía. Pero eso no es con lo que tuve problemas ni esa es la pregunta. - iglesia

@Churk, tienes razón. Por favor, vea si mis ediciones responden a su pregunta ahora. - Diego

Gracias, eso es lo que me temía, porque no tenía sentido, pero los resultados de conteo de ambos son iguales me desconcertaron. - iglesia

Para la primera consulta, es decir

SELECT a, b
FROM table1
WHERE NOT EXISTS(
  SELECT a, c
  FROM TABLE2
  WHERE table2.a != table1.a)

Esto devolverá todas las filas cuando todos los valores de a in table1 son el mismo valor y todas las filas en table2 son el mismo valor que table1 or table2 es el conjunto vacío. De lo contrario, el resultado será el conjunto vacío.

Lo mismo no puede ser lo mismo de su segunda consulta.

respondido 09 mar '12, 16:03

Gracias por dar más explicaciones, puedo ver a qué te refieres ahora. - iglesia

SELECT a, b, c , d
FROM table1 t1
WHERE NOT EXISTS( SELECT * FROM table2 nx
  WHERE nx.y = t1.a
  )
  ;

Hay una gran ventaja de este método ("subconsulta correlacionada"): la tabla tabla2 no es visible desde la consulta externa y no puede contaminarla ni confundir su pensamiento. La subconsulta solo produce un bit de información: existe o no existe. Ser o no ser ....
En ese sentido, el modismo LEFT JOIN es más desagradable, ya que tendrás que comprobar el xxx IS NULL condición en la consulta externa, mientras que xxx hace referencia a la tabla2 de la consulta interna.

Técnicamente, no hay diferencia.

respondido 09 mar '12, 16:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.