В чем разница между предложением EXISTS
и IN
в SQL?
Когда мы должны использовать EXISTS
, и когда следует использовать IN
?
В чем разница между предложением EXISTS
и IN
в SQL?
Когда мы должны использовать EXISTS
, и когда следует использовать IN
?
Ключевое слово 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
.
EXISTS
сообщит вам, возвращает ли запрос какие-либо результаты. например:.
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)
На основе оптимизатора правил:
EXISTS
намного быстрее, чем IN
, когда результаты подзапроса очень велики.IN
быстрее, чем EXISTS
, когда результаты суб-запроса очень малы.На основе оптимизатора затрат:
Я предполагаю, что вы знаете, что они делают, и поэтому используются по-разному, поэтому я буду понимать ваш вопрос так: Когда было бы хорошей идеей переписать 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 вместо этого, или наоборот, будет хорошая идея?
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'
Запрос 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
ваш id имеет нулевое значение, то Query 1 найдет их, но Query 2 не сможет найти нулевые параметры.
Я имею в виду, что IN
не может сравнивать ничего с NULL, поэтому он не имеет результата для null, но EXISTS
может сравнивать все с нулевым.
Если вы используете оператор IN
, механизм SQL будет проверять все записи, извлеченные из внутреннего запроса. С другой стороны, если мы используем EXISTS
, механизм SQL остановит процесс сканирования, как только найдет совпадение.
Ключевое слово Exists
оценивает значение true или false, но ключевое слово IN
сравнивает все значения в соответствующем столбце подзапроса.
Другой Select 1
может использоваться с командой Exists
. Пример:
SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)
Но IN
менее эффективен, поэтому Exists
быстрее.
IN поддерживает только отношения равенства (или неравенство, когда ему предшествует НЕ).
Это синоним = любой/= some, например
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 могут возникать из-за конкретных реализаций/ограничений/ошибок поставщика, но во многих случаях это ничего, кроме мифов, созданных из-за отсутствия понимания внутренних систем баз данных.
Определение таблиц, точность статистики, конфигурация базы данных и версия оптимизатора оказывают влияние на план выполнения и, следовательно, на показатели производительности.
Я думаю,
EXISTS
- это когда вам нужно сопоставить результаты запроса с другим подзапросом.
Результаты запроса # 1 должны быть получены, когда результаты SubQuery совпадают. Вид Присоединиться..
Например. выберите таблицу клиентов №1, которые также разместили таблицу заявок # 2.
IN следует извлекать, если значение конкретного столбца содержит IN
список (1,2,3,4,5)
Например. Выберите клиентов, которые находятся в следующих zipcodes, то есть значения zip_code находятся в списке (....).
Когда использовать один над другим... когда вы чувствуете, что он читает правильно (лучше взаимодействует).
Здесь разница:
select *
from abcTable
where exists (select null)
Выше запроса вернет все записи, а ниже будет возвращено пустое.
select *
from abcTable
where abcTable_ID in (select null)
Попробуйте и посмотрите результат.
Как известно, когда подзапрос возвращает значение NULL
, весь оператор становится NULL
. В этом случае мы используем ключевое слово EXITS
. Если мы хотим сравнить определенные значения в подзапросах, то мы используем ключевое слово IN
.
Какой из них быстрее, зависит от количества запросов, полученных внутренним запросом:
EXIST оценивает значение true или false, но IN сравнивает множественное значение. Когда вы не знаете, что запись существует или нет, вы должны выбрать EXIST
Причина в том, что оператор EXISTS работает на основе принципа "по крайней мере, найденного". Он возвращает true и останавливает таблицу сканирования, если найдена хотя бы одна соответствующая строка.
С другой стороны, когда оператор IN объединен с подзапросом, MySQL сначала обрабатывает подзапрос, а затем использует результат подзапроса для обработки всего запроса.
Общее правило состоит в том, что если в подзапрос содержит большой объем данных, оператор EXISTS обеспечивает лучшую производительность.
Однако запрос, который использует оператор IN, будет работать быстрее, если результирующий набор, возвращенный из подзапроса, очень мал.
Мое понимание - это то же самое, если мы не имеем дело с значениями NULL.
По той же причине, почему запрос не возвращает значение для = NULL vs имеет значение NULL. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
Как для логического аргумента сравнения или сравнения, для генерации логического значения оба значения нужно сравнивать, и именно так работает любое условие. Поэтому я не понимаю, как IN и EXISTS ведут себя по-разному ,
Если подзапрос возвращает более одного значения, вам может потребоваться выполнить внешний запрос - если значения в столбце, указанном в условии, соответствуют любому значению в результирующем наборе подзапроса. Для выполнения этой задачи вам нужно использовать ключевое слово in
.
Вы можете использовать подзапрос, чтобы проверить, существует ли набор записей. Для этого вам нужно использовать предложение exists
с подзапросом. Ключевое слово exists
всегда возвращает значение true или false.
Я считаю, что у этого есть прямой ответ. Почему бы вам не проверить его у людей, которые разработали эту функцию в своих системах?
Если вы разработчик MS SQL, вот ответ от Microsoft.
IN
:
Определяет, соответствует ли указанное значение любому значению в подзапросе или списке.
Задает подзапрос для проверки существования строк.
Я обнаружил, что использование ключевого слова EXISTS часто очень медленное (это очень верно в Microsoft Access). Вместо этого я использую оператор объединения таким образом: should-i-use-the-keyword-exists-in-sql
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.
https://docs.oracle.com/cd/B19306_01/server.102/b14211/sql_1016.htm#i28403
EXISTS работает быстрее, чем IN. Если большинство критериев фильтра находится в подзапросе, тогда лучше использовать IN и если большинство критериев фильтра находится в основном запросе, то лучше использовать EXISTS.
Если вы используете оператор IN, механизм SQL будет сканировать все записи, извлеченные из внутреннего запроса. С другой стороны, если мы используем EXISTS, механизм SQL остановит процесс сканирования, как только найдет совпадение.