Pregunta

Acabo de aprender (ayer) a usar "existe" en lugar de " en " ;.

 BAD
 select * from table where nameid in ( 
          select nameid from othertable where otherdesc =  'SomeDesc' )      
 GOOD
 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      

Y tengo algunas preguntas sobre esto:

1) La explicación tal como la entendí fue: " La razón por la cual esto es mejor es porque solo se devolverán los valores coincidentes en lugar de construir una lista masiva de resultados posibles " . ¿Eso significa que si bien la primera subconsulta puede devolver 900 resultados, la segunda devolverá solo 1 (sí o no)?

2) En el pasado tuve el RDBMS quejándose: "solo se podrían recuperar las primeras 1000 filas", ¿este segundo enfoque resolvería ese problema?

3) ¿Cuál es el alcance del alias en la segunda subconsulta? ... ¿el alias solo vive entre paréntesis?

por ejemplo

 select * from table t where exists ( 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeDesc' )      
 AND 
          select nameid from othertable o where t.nameid = o.nameid and otherdesc =  'SomeOtherDesc' )      

Es decir, si uso el mismo alias (o para la tabla othertable) En el segundo " existe " ¿Presentará algún problema con el primero? o son totalmente independientes?

¿Esto es algo relacionado con Oracle o es válido para la mayoría de los RDBMS?

Muchas gracias

¿Fue útil?

Solución

Es específico para cada DBMS y depende del optimizador de consultas. Algunos optimizadores detectan la cláusula IN y la traducen.

En todos los DBMS que probé, el alias solo es válido dentro de ()

Por cierto, puede reescribir la consulta como:

select t.* 
from table t 
join othertable o on t.nameid = o.nameid 
    and o.otherdesc in ('SomeDesc','SomeOtherDesc');

Y, para responder a sus preguntas:

Otros consejos

Estás pisando un territorio complicado, conocido como 'subconsultas correlacionadas'. Como no tenemos información detallada sobre sus tablas y las estructuras clave, algunas de las respuestas solo pueden ser 'quizás'.

En su consulta IN inicial, la notación sería válida si OtherTable contiene o no una columna NameID (y, de hecho, si OtherDesc existe como una columna en Table u OtherTable, lo cual no está claro en ninguno de sus ejemplos, pero presumiblemente es una columna de OtherTable). Este comportamiento es lo que convierte una subconsulta correlacionada en una subconsulta correlacionada. También es una fuente rutinaria de angustia para las personas cuando se encuentran por primera vez, invariablemente por accidente. Dado que el estándar SQL exige el comportamiento de interpretar un nombre en la subconsulta como una referencia a una columna en la consulta externa si no hay una columna con el nombre relevante en las tablas mencionadas en la subconsulta pero hay una columna con el nombre relevante en las tablas mencionadas en la consulta externa (principal), ningún producto que quiera reclamar conformidad con (este bit) del estándar SQL hará algo diferente.

La respuesta a su Q1 es '' depende '', pero dados supuestos plausibles (NameID existe como una columna en ambas tablas; OtherDesc solo existe en OtherTable), los resultados deben ser los mismos en términos del conjunto de datos devuelto, pero puede no ser equivalente en términos de rendimiento.

La respuesta a su Q2 es que en el pasado, estaba usando un DBMS inferior, si no defectuoso. Si era compatible con EXISTS, el DBMS aún podría quejarse de la cardinalidad del resultado.

La respuesta a su Q3 aplicada a la primera consulta EXISTS es "t está disponible como un alias en toda la instrucción, pero o solo está disponible como un alias dentro de los paréntesis". Según se aplica a su segundo cuadro de ejemplo: con AND conectando dos sub-selecciones (al segundo le falta el paréntesis abierto cuando lo estoy mirando), entonces & t; está disponible como un alias en todo el enunciado y se refiere al misma tabla, pero hay dos alias diferentes, ambos etiquetados como 'o', uno para cada subconsulta " ;. Tenga en cuenta que la consulta podría no devolver datos si OtherDesc es único para un valor NameID dado en OtherTable; de lo contrario, requiere dos filas en OtherTable con el mismo NameID y los dos valores de OtherDesc para cada fila en Table con ese valor de NameID.

  1. Específico de Oracle: cuando escribe una consulta utilizando la cláusula IN, le está diciendo al optimizador basado en reglas que desea que la consulta interna controle la consulta externa. Cuando escribe EXISTS en una cláusula where, le está diciendo al optimizador que desea que la consulta externa se ejecute primero, utilizando cada valor para obtener un valor de la consulta interna. Consulte " Diferencia entre IN y EXISTS en subconsultas " .
  2. Probablemente.
  3. El alias declarado dentro de la subconsulta vive dentro de la subconsulta. Por cierto, no creo que su ejemplo con 2 subconsultas ANDed sea SQL válido. ¿Quiso decir UNION en lugar de AND?

Personalmente, usaría una combinación, en lugar de una subconsulta para esto.

SELECT t.*
FROM yourTable t
    INNER JOIN otherTable ot
        ON (t.nameid = ot.nameid AND ot.otherdesc = 'SomeDesc')

Es difícil generalizar que EXISTE siempre es mejor que IN. Lógicamente, si ese es el caso, la comunidad SQL habría reemplazado IN con EXISTS ... Además, tenga en cuenta que IN y EXISTS no son iguales, los resultados pueden ser diferentes cuando utiliza los dos ...

Con IN, por lo general es una exploración de tabla completa de la tabla interna una vez sin eliminar NULL (por lo tanto, si tiene NULLs en su tabla interna, IN no eliminará NULLS por defecto) ... Mientras que EXISTS elimina NULL y en caso de subconsulta correlacionada, ejecuta una consulta interna para cada fila desde una consulta externa.

Suponiendo que no hay NULLS y es una consulta simple (sin correlación), EXIST podría funcionar mejor si la fila que está encontrando no es la última fila. Si resulta ser la última fila, es posible que EXISTA necesite escanear hasta el final como IN ... un rendimiento similar ...

Pero IN y EXISTS no son intercambiables ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top