Ответы:
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утверждении, имеет смысл использовать a join, но в основном это не должно иметь значения. Оптимизатор запросов должен возвращать тот же план в любом случае. В некоторых реализациях (в основном старых, таких как Microsoft SQL Server 2000) inзапросы всегда получают вложенный план соединения , тогда как joinзапросы будут использовать вложенные, слияния или хэширования в зависимости от ситуации. Более современные реализации умнее и могут корректировать план даже при inиспользовании.
select * from [table] where [field] in (select [field] from [table2])возвращает те же результаты (и план запроса), что и select * from [table] join [table2] on [table2].[field] = [table].[field].
table, а второй возвращает все из tableи table2. В некоторых (в основном старых) базах данных SQL inзапрос будет реализован как вложенное объединение, в то время как joinзапрос может быть вложенным, объединенным, хэшированным и т. Д. - как угодно быстро.
existsможет использоваться внутри оператора case, поэтому они могут быть полезны и в этом случае, например:select case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
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, или наоборот, будет хорошей идеей?
JOIN, вам понадобитсяDISTINCT
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ничего нельзя сравнить с нулем, поэтому он не имеет результата для нуля, но EXISTSможет сравнить все с нулем.
Если вы используете INоператор, механизм SQL будет сканировать все записи, извлеченные из внутреннего запроса. С другой стороны, если мы используем EXISTS, движок SQL остановит процесс сканирования, как только найдет совпадение.
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 могут быть результатом реализаций / ограничений / ошибок конкретного поставщика, но во многих случаях они являются не более чем мифами, созданными из-за непонимания внутренних структур баз данных.
Определение таблиц, точность статистики, конфигурация базы данных и версия оптимизатора оказывают влияние на план выполнения и, следовательно, на показатели производительности.
ExistsКлючевое слово оценивает истинным или ложным, но INключевое слово сравнить все значения в соответствующем столбце юга запроса. Еще один Select 1можно использовать с Existsкомандой. Пример:
SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)
Но INменее эффективно, так Existsбыстрее.
Я думаю,
EXISTSэто когда вам нужно сопоставить результаты запроса с другим подзапросом. Результаты запроса # 1 должны быть получены там, где совпадают результаты SubQuery. Вид присоединения. Например, таблица клиентов № 1, которые также разместили таблицу заказов № 2
IN предназначен для извлечения, если значение определенного столбца находится INв списке (1,2,3,4,5). Например, выберите клиентов, которые находятся в следующих почтовых индексах, т.е. значения zip_code находятся в (....) списке.
Когда использовать один поверх другого ... когда вы чувствуете, что он читается соответствующим образом (лучше информирует о намерениях).
Разница заключается здесь:
select *
from abcTable
where exists (select null)
Выше запрос вернет все записи, а ниже один вернется пустым.
select *
from abcTable
where abcTable_ID in (select null)
Попробуйте и посмотрите на результат.
Какой из них быстрее, зависит от количества запросов, извлекаемых внутренним запросом:
EXIST оценивает на true или false, но IN сравнивает множественное значение. Если вы не знаете, существует запись или нет, вы должны выбрать EXIST
Причина в том, что оператор EXISTS работает по принципу «как минимум найден». Возвращает true и останавливает сканирование таблицы, если найдена хотя бы одна подходящая строка.
С другой стороны, когда оператор IN объединяется с подзапросом, MySQL должен сначала обработать подзапрос, а затем использовать результат подзапроса для обработки всего запроса.
Общее правило заключается в том, что если подзапрос содержит большой объем данных, оператор EXISTS обеспечивает лучшую производительность.
Однако запрос, использующий оператор IN, будет выполняться быстрее, если набор результатов, возвращаемый из подзапроса, очень мал.
Я понимаю, что оба должны быть одинаковыми, если мы не имеем дело со значениями NULL.
По той же причине, по которой запрос не возвращает значение для = NULL против NULL. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
Что касается аргумента «булево против компаратора», то для генерации логического значения необходимо сравнить оба значения, и вот как работает любое условие. Поэтому я не могу понять, как IN и EXISTS ведут себя по-разному.
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
Если подзапрос возвращает более одного значения, вам может потребоваться выполнить внешний запрос - если значения в столбце, указанном в условии, соответствуют какому-либо значению в наборе результатов подзапроса. Для выполнения этой задачи вам необходимо использовать inключевое слово.
Вы можете использовать подзапрос, чтобы проверить, существует ли набор записей. Для этого вам нужно использовать existsпредложение с подзапросом. existsКлючевое слово всегда возвращает истинное или ложное значение.
Я считаю, что это имеет прямой ответ. Почему бы вам не проверить это у людей, которые разработали эту функцию в своих системах?
Если вы являетесь разработчиком MS SQL, вот ответ непосредственно от Microsoft.
IN:
Определяет, соответствует ли указанное значение какому-либо значению в подзапросе или списке.
Определяет подзапрос для проверки существования строк.
Я обнаружил, что использование ключевого слова EXISTS часто очень медленно (это очень верно в Microsoft Access). Вместо этого я использую оператор соединения следующим образом: should-i-use-the-keyword-существующие-in-sql
EXISTS быстрее в производительности, чем IN. Если большинство критериев фильтра находится в подзапросе, то лучше использовать IN, а если большинство критериев фильтра находится в основном запросе, то лучше использовать EXISTS.
Если вы используете оператор IN, механизм SQL будет сканировать все записи, извлеченные из внутреннего запроса. С другой стороны, если мы используем EXISTS, механизм SQL остановит процесс сканирования, как только найдет совпадение.
INи EXISTSможет быть эквивалентным и преобразованным друг в друга.
JOINее вместоIN.