Разница между EXISTS и IN в SQL? - PullRequest
       91

Разница между EXISTS и IN в SQL?

412 голосов
/ 24 августа 2008

В чем разница между предложениями EXISTS и IN в SQL?

Когда мы должны использовать EXISTS, и когда мы должны использовать IN?

Ответы [ 20 ]

214 голосов
/ 24 августа 2008

Ключевое слово exists может использоваться таким образом, но на самом деле оно предназначено как способ избежать подсчета:

--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 ... )

Это наиболее полезно, когда у вас есть if условные операторы, поскольку exists может быть намного быстрее, чем count.

in лучше всего использовать, когда вам нужно передать статический список:

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

Если в операторе in есть таблица, имеет смысл использовать join, но в основном это не должно иметь значения. Оптимизатор запросов должен возвращать тот же план в любом случае. В некоторых реализациях (в основном старых, таких как Microsoft SQL Server 2000) запросы in всегда будут иметь план вложенного соединения , в то время как запросы join будут использовать вложенные, merge или хэш в зависимости от ситуации. Более современные реализации умнее и могут корректировать план даже при использовании in.

117 голосов
/ 24 августа 2008

EXISTS сообщит вам, дал ли запрос какие-либо результаты. e.g.:

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

IN используется для сравнения одного значения с несколькими и может использовать литеральные значения, например:

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

Вы также можете использовать результаты запроса с предложением IN, например:

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0)
81 голосов
/ 19 октября 2010

На основе оптимизатора правил :

  • EXISTS намного быстрее, чем IN, когда результаты подзапроса очень велики.
  • IN быстрее, чем EXISTS, когда результаты подзапроса очень малы.

На основе оптимизатора затрат :

  • Нет никакой разницы.
40 голосов
/ 24 августа 2008

Я предполагаю, что вы знаете, что они делают, и, следовательно, используются по-разному, поэтому я пойму ваш вопрос следующим образом: Когда было бы хорошей идеей переписать SQL-код, чтобы использовать IN вместо EXISTS, или наоборот? наоборот.

Это справедливое предположение?


Редактировать : причина, по которой я спрашиваю, состоит в том, что во многих случаях вы можете переписать SQL на основе IN, чтобы вместо него использовать EXISTS, и наоборот, а для некоторых механизмов баз данных оптимизатор запросов будет относиться к ним по-разному.

Например:

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

можно переписать на:

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

или с объединением:

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

Таким образом, мой вопрос остается в силе, будет ли оригинальный постер интересоваться тем, что делает IN и EXISTS, и, таким образом, как его использовать, или он попросит, переписать ли SQL с использованием IN вместо EXISTS, или наоборот, будет хорошая идея?

28 голосов
/ 04 июля 2012
  1. EXISTS намного быстрее, чем IN, когда результаты подзапроса очень велики.
    IN быстрее, чем EXISTS, когда результаты подзапроса очень малы.

    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. Запрос 1

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

    Запрос 2

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

    Если в t1 ваш идентификатор имеет нулевое значение, тогда Query 1 найдет их, но Query 2 не может найти нулевые параметры.

    Я имею в виду IN не может сравнивать что-либо с нулем, поэтому он не имеет результата для нуля, но EXISTS может сравнивать все с нулем.

16 голосов
/ 16 июля 2013

Если вы используете оператор IN, механизм SQL будет сканировать все записи, извлеченные из внутреннего запроса. С другой стороны, если мы используем EXISTS, механизм SQL остановит процесс сканирования, как только найдет совпадение.

10 голосов
/ 07 октября 2016

IN поддерживает только отношения равенства (или неравенства, когда им предшествует NOT ).
Это синоним = любой / = некоторый , например,

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

EXISTS поддерживает различные типы отношений, которые не могут быть выражены с помощью IN , например, -

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 || '℅'
                  )
;

И на другой ноте -

Предполагаемая производительность и технические различия между EXISTS и IN могут быть результатом реализации / ограничений / ошибок конкретного поставщика, но во многих случаях они являются не чем иным, как мифами, созданными из-за отсутствия понимания внутренних баз данных.

Определение таблиц, точность статистики, конфигурация базы данных и версия оптимизатора оказывают влияние на план выполнения и, следовательно, на показатели производительности.

9 голосов
/ 25 мая 2012

Ключевое слово Exists оценивает true или false, но ключевое слово IN сравнивает все значения в соответствующем столбце подзапроса. Другой Select 1 можно использовать с командой Exists. Пример:

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

Но IN менее эффективен, поэтому Exists быстрее.

5 голосов
/ 24 августа 2008

Я думаю,

  • EXISTS - это когда вам нужно сопоставить результаты запроса с другим подзапросом. Результаты запроса # 1 должны быть получены там, где совпадают результаты SubQuery. Вид присоединения .. Например. выберите таблицу клиентов № 1, которые также разместили таблицу заказов № 2

  • IN предназначен для получения, если значение определенного столбца лежит IN список (1,2,3,4,5) Например. Выберите клиентов, которые находятся в следующих почтовых индексах, т.е. значения zip_code находятся в списке (....).

Когда использовать один поверх другого ... когда вы чувствуете, что он читается надлежащим образом (лучше информирует о намерениях).

4 голосов
/ 19 мая 2015

Разница лежит здесь:

select * 
from abcTable
where exists (select null)

Выше запрос вернет все записи, в то время как ниже один вернет пустое.

select *
from abcTable
where abcTable_ID in (select null)

Попробуйте и посмотрите на результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...