Відповіді:
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
їх можна використовувати в заяві справи, тому вони також можуть бути зручними, тобто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
вашому ідентифікаторі є нульове значення, запит 1 знайде їх, але запит 2 не може знайти нульові параметри.
Я маю на увазі, що IN
не можна нічого порівнювати з null, тому це не має результату для null, але я EXISTS
можу порівнювати все з null.
Якщо ви використовуєте IN
оператор, SQL-движок сканує всі записи, отримані з внутрішнього запиту. З іншого боку, якщо ми використовуємо EXISTS
, двигун SQL зупинить процес сканування, як тільки знайде відповідність.
IN підтримує лише відносини рівності (або нерівності, коли передує НЕ ).
Це синонім = будь-який / = якийсь , наприклад
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)
Спробуйте спробувати і спостерігати за результатами.
Який з них швидший, залежить від кількості запитів, отриманих внутрішнім запитом:
ІСНУЮТЬ оцінювати за істинним чи хибним, але IN порівнювати кратне значення. Якщо ви не знаєте, чи існує запис чи немає, слід вибрати EXIST
Причина полягає в тому, що оператор EXISTS працює за принципом "принаймні знайденого". Він повертає істину і зупиняє сканувати таблицю, як тільки знайдено принаймні одну відповідну рядок.
З іншого боку, коли оператор IN поєднується з підзапитом, MySQL спочатку повинен обробити підзапит, а потім використовує результат підзапиту для обробки всього запиту.
Загальне правило: якщо підзапит містить великий об'єм даних, оператор EXISTS забезпечує кращу ефективність.
Однак запит, який використовує оператор IN, буде виконуватись швидше, якщо набір результатів, повернутий з підзапиту, дуже малий.
Я розумію, що обидва повинні бути однаковими, доки ми не маємо справу з значеннями NULL.
Ця ж причина, чому запит не повертає значення для = NULL vs NULL. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
Що стосується аргументу булева проти компаратора, то для створення булевих обох значень потрібно порівнювати, і це так, як будь-яке, якщо умова працює.
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). Я замість цього використовую оператор приєднання таким чином: повинен-я-використовувати-ключове слово-існує-в-sql
ІСНУЄТЕ Швидше за продуктивністю, ніж IN. Якщо більшість критеріїв фільтра знаходиться в підзапиті, тоді краще використовувати IN і якщо більшість критеріїв фільтра знаходиться в головному запиті, тоді краще використовувати EXISTS.
Якщо ви використовуєте оператор IN, движок SQL сканує всі записи, отримані з внутрішнього запиту. З іншого боку, якщо ми використовуємо EXISTS, двигун SQL зупинить процес сканування, як тільки знайде відповідність.
IN
і EXISTS
можуть бути рівнозначними і перетворюватися один в одного.
JOIN
замінуIN
.