2008-08-24 67 views

Respuesta

37

Supongo que sabes lo que hacen, y por lo tanto se usan de manera diferente, así que voy a entender tu pregunta como: ¿Cuándo sería una buena idea reescribir el SQL para usar IN en lugar de EXISTS, o viceversa.

¿Es eso una suposición razonable?


Editar: La razón por la que estoy pidiendo es que en muchos casos se puede volver a escribir una consulta SQL basado en IN para utilizar un EXISTS lugar, y viceversa, y para algunos motores de bases de datos, el optimizador de consultas tratar a los dos de manera diferente.

Por ejemplo:

SELECT * 
FROM Customers 
WHERE EXISTS (
    SELECT * 
    FROM Orders 
    WHERE Orders.CustomerID = Customers.ID 
) 

puede reescribirse a:

SELECT * 
FROM Customers 
WHERE ID IN (
    SELECT CustomerID 
    FROM Orders 
) 

o con una combinación:

SELECT Customers.* 
FROM Customers 
    INNER JOIN Orders ON Customers.ID = Orders.CustomerID 

Así que mi pregunta sigue en pie, es el creador original se pregunta sobre qué hace IN y EXISTS, y por lo tanto cómo usarlo, o pregunta si reescribir un SQL usando IN para usar EXISTS instea d, o viceversa, será una buena idea?

+10

no sé acerca de la OP, pero me gustaría que la respuesta a esta pregunta! ¿Cuándo debería usar EXISTS en lugar de IN con una subconsulta que devuelve IDs? –

+7

en el 'JOIN', necesitará una gran demostración 'DISTINCT' – Jaider

+2

, pero prácticamente deje la pregunta sin respuesta –

107

EXISTS le dirá si una consulta arrojó algún resultado. por ejemplo:

SELECT * 
FROM Orders o 
WHERE EXISTS (
    SELECT * 
    FROM Products p 
    WHERE p.ProductNumber = o.ProductNumber) 

IN se utiliza para comparar un valor de varios, y se puede utilizar valores literales, como esto:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (1, 10, 100) 

También puede utilizar los resultados de la consulta con la cláusula IN, así:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0) 
+2

La última consulta es peligrosa porque podría fallar en el caso de que la subconsulta no arroje ningún resultado. La cláusula 'in' requiere al menos 1 argumento ... – user2054927

+21

@ user2054927 La última consulta devolverá correctamente las filas si la subconsulta no devuelve filas, ¡nada peligroso sobre eso! –

5

pienso,

  • EXISTS es cuando necesita hacer coincidir los resultados de la consulta con otra subconsulta. Los resultados de Query # 1 deben recuperarse cuando coinciden los resultados de SubQuery. Tipo de unir .. E.g. tabla de clientes selectos # 1 que han hecho pedidos tabla # 2 también

  • in es recuperar si el valor de una columna específica se encuentra IN una lista (1,2,3,4,5) P. ej Seleccione los clientes que se encuentran en los siguientes códigos postales, es decir, los valores de zip_code se encuentran en la lista (....).

Cuándo usar uno sobre el otro ... cuando sienta que se lee correctamente (Comunica la intención mejor).

186

El exists palabra clave puede utilizarse de esa manera, pero en realidad es pensado como una manera de evitar el conteo:

--this statement needs to check the entire table 
select count(*) from [table] where ... 

--this statement is true as soon as one match is found 
exists (select * from [table] where ...) 

Esto es muy útil cuando usted tiene if sentencias condicionales, como exists puede ser una mucho más rápido que count.

El in se utiliza mejor cuando usted tiene una lista estática de pasar:

select * from [table] 
where [field] in (1, 2, 3) 

Cuando se tiene una tabla en una declaración in que tiene más sentido utilizar un join, pero sobre todo no debe importar . El optimizador de consultas debe devolver el mismo plan de cualquier manera. En algunas implementaciones (mayormente antiguas, como Microsoft SQL Server 2000) las consultas in siempre obtendrán un plan nested join, mientras que las consultas join usarán anidado, merge o hash según corresponda. Las implementaciones más modernas son más inteligentes y pueden ajustar el plan incluso cuando se usa in.

+2

¿Podría profundizar en "Cuando tiene una tabla en una declaración en que tiene más sentido usar una combinación, pero en realidad no importa. El optimizador de consultas devolverá el mismo plan en ambos sentidos"? No es la parte del optimizador de consultas, la parte donde puede usar un 'JOIN' como reemplazo de 'IN'. – farthVader

+0

'select * from [table] donde [field] in (select [field] from [table2])' devuelve los mismos resultados (y plan de consulta) que 'select * from [table] join [table2] on [table2]. [campo] = [tabla]. [campo] '. –

+0

@Sander no: la primera consulta devuelve todas las columnas de 'tabla', mientras que la segunda devuelve todo de' tabla' y 'tabla2'. En algunas bases de datos SQL (mayoritariamente), la consulta 'in' se implementará como una unión anidada, mientras que la consulta' join' se puede anidar, fusionar, hash, etc., lo que sea más rápido. – Keith

75

Basado en optimizador regla:

  • EXISTS es mucho más rápido que IN, cuando los resultados sub-consulta es muy grande.
  • IN es más rápido que EXISTS, cuando los resultados de la sub consulta son muy pequeños.

Basado en costo optimizador:

  • No hay ninguna diferencia.
+17

¿Prueba de su argumento? ¡No creo que IN sea más rápido que EXISTS! – Nawaz

+16

@Nawaz ¿Qué tal la prueba de por qué IN siempre es más lento que EXISTS? – ceving

+2

¿Optimizador de consultas mal implementado? Parece que algo así (aunque no exactamente esta situación) ocurre en ciertos RDBM ... –

3

Según mi conocimiento cuando una subconsulta devuelve un valor de NULL, toda la instrucción se convierte en NULL. En esos casos, estamos utilizando la palabra clave EXITS. Si queremos comparar valores particulares en subconsultas, estamos utilizando la palabra clave IN.

8

La palabra clave Exists evalúa verdadero o falso, pero la palabra clave IN compara todos los valores en la columna correspondiente de la sub consulta. Otro Select 1 puede usarse con el comando Exists. Ejemplo:

SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...) 

Pero IN es menos eficiente por lo Exists más rápido.

-2

Si está utilizando el operador IN, el motor SQL escaneará todos los registros obtenidos de la consulta interna. Por otro lado, si estamos utilizando EXISTS, el motor de SQL detendrá el proceso de escaneo tan pronto como encuentre una coincidencia.

+0

Eso no es correcto. – ziggy

+0

@ziggy explicar? Esto es más o menos lo que también dice la respuesta aceptada. En DEBE verificar cada registro individual, existe puede detenerse tan pronto como encuentre solo uno. –

+0

No, no es correcto. 'IN' y' EXISTS' pueden ser equivalentes y transformarse entre sí. –

26
  1. EXISTS es mucho más rápido que cuando los resultados IN subconsulta es muy grande.
    IN es más rápido que EXISTS cuando los resultados de la subconsulta son muy pequeños.

    CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT) 
    GO 
    CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20)) 
    GO 
    
    INSERT INTO t1 
    SELECT 1, 'title 1', 5 UNION ALL 
    SELECT 2, 'title 2', 5 UNION ALL 
    SELECT 3, 'title 3', 5 UNION ALL 
    SELECT 4, 'title 4', 5 UNION ALL 
    SELECT null, 'title 5', 5 UNION ALL 
    SELECT null, 'title 6', 5 
    
    INSERT INTO t2 
    SELECT 1, 1, 'data 1' UNION ALL 
    SELECT 2, 1, 'data 2' UNION ALL 
    SELECT 3, 2, 'data 3' UNION ALL 
    SELECT 4, 3, 'data 4' UNION ALL 
    SELECT 5, 3, 'data 5' UNION ALL 
    SELECT 6, 3, 'data 6' UNION ALL 
    SELECT 7, 4, 'data 7' UNION ALL 
    SELECT 8, null, 'data 8' UNION ALL 
    SELECT 9, 6, 'data 9' UNION ALL 
    SELECT 10, 6, 'data 10' UNION ALL 
    SELECT 11, 8, 'data 11' 
    
  2. Consulta 1

    SELECT 
    FROM t1 
    WHERE not EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id) 
    

    Consulta 2

    SELECT t1.* 
    FROM t1 
    WHERE t1.id not in (SELECT t2.t1id FROM t2) 
    

    Si en t1 su ID tiene valor nulo a continuación, consulta 1 será encontrarlos, pero Consulta 2 no puede encontrar parámetros nulos.

    O sea, IN no se puede comparar nada con nulo, por lo que no tiene resultados para null, pero EXISTS puede comparar todo con null.

+0

Esta respuesta es una sinopsis razonable del sentimiento de Tom Kite (http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:953229842074) –

+0

Creo que esta respuesta se basa en la intuición , que es bastante justo Pero no puede ser universalmente cierto. Por ejemplo, es casi seguro que no es cierto de [Ingres] (https://en.wikipedia.org/wiki/Ingres_ (base de datos)), que analizaría las dos consultas SQL equivalentes para ser la misma consulta QUEL, que carece de SQL - ejem - 'riqueza' cuando se trata de escribir lo mismo de múltiples maneras. – onedaywhen

+0

Estas 2 consultas son lógicamente equivalentes si y solo si t2.id se define como "NOT NULL". Para otorgar la equivalencia sin dependencia en la definición de la tabla, la segunda consulta debe ser "SELECCIONE t1. * DESDE t1 DONDE t1.id no está en (SELECCIONE t2.id DESDE t2 * donde t2.id no es nulo *)" –

0

Si una sentencia devuelve más de un valor, puede que tenga que ejecutar la query- exterior si los valores dentro de la columna especificada en la condición encontró ningún valor en el conjunto de resultados de la subconsulta. Para realizar esta tarea, debe usar la palabra clave in.

Puede usar una subconsulta para verificar si existe un conjunto de registros. Para esto, debe usar la cláusula exists con una subconsulta. La palabra clave exists siempre devuelve valor verdadero o falso.

-1

EXISTS Tiene un rendimiento más rápido que IN. Si la mayoría de los criterios de filtro están en subconsulta, es mejor usar IN y si la mayoría de los criterios de filtro están en la consulta principal, entonces es mejor utilizar EXISTS.

+0

Ese reclamo realmente no está respaldado por ninguna evidencia, ¿o sí? –

3

Cuál es más rápido depende del número de consultas fue a buscar por la consulta interna:

  • Cuando su consulta interna ir a buscar miles de filas continuación EXISTE sería mejor opción
  • Cuando su consulta interna ir a buscar unas filas , IN será más rápido

EXIST evaluar en verdadero o falso, pero IN comparar múltiples valores. Cuando no sabe si el registro existe o no, debe elegir EXIST

13

Si está utilizando el operador IN, el motor SQL escaneará todos los registros obtenidos de la consulta interna. Por otro lado, si estamos usando EXISTS, el motor SQL detendrá el proceso de escaneo tan pronto como encuentre una coincidencia.

+9

qué nombre de usuario apropiado ... – whoan

4

diferencia radica aquí:

select * 
from abcTable 
where exists (select null) 

Por encima de consulta devolverá todos los registros mientras que por debajo se podría volver vacíos.

select * 
from abcTable 
where abcTable_ID in (select null) 

Pruébela y observe la salida.

+1

Hmmm ... Error: [SQL0104] Token) no era válido. En ambos casos. ¿Estás asumiendo un RDBMS en particular? – jmarkmurphy

3

El motivo es que el operador EXISTS funciona según el principio "al menos encontrado". Devuelve verdadero y deja de explorar la tabla una vez que se encuentra al menos una fila coincidente.

Por otro lado, cuando el operador IN se combina con una subconsulta, MySQL debe procesar primero la subconsulta y luego utiliza el resultado de la subconsulta para procesar toda la consulta.

The general rule of thumb is that if the subquery contains a large volume of data, the EXISTS operator provides a better performance.

However, the query that uses the IN operator will perform faster if the result set returned from the subquery is very small.

1

Mi comprensión es que ambas deberían ser iguales siempre que no se trate de valores NULL.

La misma razón por la cual la consulta no devuelve el valor para = NULL vs es NULL. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/

En cuanto a As Boolean vs argumento comparador va, para generar un valor lógico ambos valores debe compararse y así es como cualquier condición works.So si no llego a entender cómo IN y EXISTE comportan de manera diferente .

5

EN sólo admite las relaciones de igualdad o desigualdad (cuando está precedido por NO).
Es un sinónimo para = cualquier/= alguna, por ejemplo

select * 
from  t1 
where  x in (select x from t2) 
; 

EXISTS soporta tipos de variantes de relaciones, que no se puede expresar utilizando EN, por ejemplo -

select * 
from  t1 
where  exists (select null 
        from  t2 
        where  t2.x=t1.x 
         and t2.y>t1.y 
         and t2.z like '℅' || t1.z || '℅' 
       ) 
; 

Y en una nota diferente -

El supuestamente rendimiento y las diferencias técnicas entre EXISTE y EN puede resultar de proveedor de concreto implementaciones/limitaciones/insectos, pero muchas veces no son más que mitos creados debido a la falta de comprensión de las bases de datos internas.

La definición de las tablas, la precisión de las estadísticas, la configuración de la base de datos y la versión del optimizador tienen impacto en el plan de ejecución y, por lo tanto, en las métricas de rendimiento.

+0

Votación a favor por su comentario sobre el rendimiento: sin centrarse en un DBMS específico, deberíamos suponer que depende del optimizador determinar qué funciona mejor. – Manngo

0

Creo que esto tiene una respuesta directa. ¿Por qué no lo compruebas de las personas que desarrollaron esa función en sus sistemas?

Si usted es un desarrollador de MS SQL, aquí está la respuesta directamente de Microsoft.

IN:

Determines whether a specified value matches any value in a subquery or a list.

EXISTS:

Specifies a subquery to test for the existence of rows.

0

He encontrado que el uso de palabras clave EXISTE es a menudo muy lento (esto es muy cierto en Microsoft Access). que en lugar de utilizar el operador unirse de esta manera: should-i-use-the-keyword-exists-in-sql

Cuestiones relacionadas