Réponses:
Le exists
mot-clé peut être utilisé de cette façon, mais il est vraiment destiné à éviter de compter:
--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 ... )
C'est très utile lorsque vous avez des if
instructions conditionnelles, car cela exists
peut être beaucoup plus rapide que count
.
Le in
mieux est utilisé lorsque vous avez une liste statique à transmettre:
select * from [table]
where [field] in (1, 2, 3)
Lorsque vous avez un tableau dans une in
instruction, il est plus logique d'utiliser un join
, mais surtout cela ne devrait pas avoir d'importance. L'optimiseur de requêtes doit renvoyer le même plan dans les deux cas. Dans certaines implémentations (généralement plus anciennes, telles que Microsoft SQL Server 2000), les in
requêtes obtiendront toujours un plan de jointure imbriqué , tandis que les join
requêtes utiliseront imbriqué, fusionner ou hacher selon le cas. Des implémentations plus modernes sont plus intelligentes et peuvent ajuster le plan même lorsqu'il in
est utilisé.
select * from [table] where [field] in (select [field] from [table2])
renvoie les mêmes résultats (et plan de requête) que select * from [table] join [table2] on [table2].[field] = [table].[field]
.
table
, tandis que la seconde renvoie tout de table
et table2
. Dans certaines bases de données SQL (pour la plupart plus anciennes), la in
requête sera implémentée en tant que jointure imbriquée, tandis que la join
requête peut être imbriquée, fusionnée, hachée, etc. - ce qui est le plus rapide.
exists
peuvent être utilisés dans une déclaration de cas, ils peuvent donc être utiles de cette façon, c'estselect case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
EXISTS
vous indiquera si une requête a renvoyé des résultats. par exemple:
SELECT *
FROM Orders o
WHERE EXISTS (
SELECT *
FROM Products p
WHERE p.ProductNumber = o.ProductNumber)
IN
est utilisé pour comparer une valeur à plusieurs, et peut utiliser des valeurs littérales, comme ceci:
SELECT *
FROM Orders
WHERE ProductNumber IN (1, 10, 100)
Vous pouvez également utiliser des résultats de requête avec la IN
clause, comme ceci:
SELECT *
FROM Orders
WHERE ProductNumber IN (
SELECT ProductNumber
FROM Products
WHERE ProductInventoryQuantity > 0)
Basé sur l' optimiseur de règles :
EXISTS
est beaucoup plus rapide que IN
lorsque les résultats de la sous-requête sont très importants.IN
est plus rapide que EXISTS
lorsque les résultats de la sous-requête sont très petits.Basé sur l' optimiseur de coûts :
Je suppose que vous savez ce qu'ils font et que vous les utilisez donc différemment, je vais donc comprendre votre question comme suit: quand serait-ce une bonne idée de réécrire le SQL pour utiliser IN au lieu d'EXISTS, ou vice versa.
Est-ce une hypothèse juste?
Edit : La raison pour laquelle je demande est que dans de nombreux cas, vous pouvez réécrire un SQL basé sur IN pour utiliser un EXISTS à la place, et vice versa, et pour certains moteurs de base de données, l'optimiseur de requête traitera les deux différemment.
Par exemple:
SELECT *
FROM Customers
WHERE EXISTS (
SELECT *
FROM Orders
WHERE Orders.CustomerID = Customers.ID
)
peut être réécrit en:
SELECT *
FROM Customers
WHERE ID IN (
SELECT CustomerID
FROM Orders
)
ou avec une jointure:
SELECT Customers.*
FROM Customers
INNER JOIN Orders ON Customers.ID = Orders.CustomerID
Donc ma question est toujours d'actualité, est-ce que l'affiche originale se demande ce que fait IN et EXISTS, et donc comment l'utiliser, ou demande-t-il si la réécriture d'un SQL utilisant IN pour utiliser EXISTS à la place, ou vice versa, sera une bonne idée?
JOIN
, vous aurez besoin d'unDISTINCT
EXISTS
est beaucoup plus rapide que IN
lorsque les résultats de la sous-requête sont très importants.
IN
est plus rapide que EXISTS
lorsque les résultats de la sous-requête sont très petits.
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'
Requête 1
SELECT
FROM t1
WHERE not EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
Requête 2
SELECT t1.*
FROM t1
WHERE t1.id not in (SELECT t2.t1id FROM t2 )
Si t1
votre identifiant a une valeur nulle, la requête 1 les trouvera, mais la requête 2 ne trouvera pas de paramètres nuls.
Je veux dire IN
ne peut rien comparer avec null, donc il n'a aucun résultat pour null, mais EXISTS
peut tout comparer avec null.
Si vous utilisez l' IN
opérateur, le moteur SQL analysera tous les enregistrements extraits de la requête interne. D'un autre côté, si nous utilisons EXISTS
, le moteur SQL arrêtera le processus d'analyse dès qu'il aura trouvé une correspondance.
IN prend uniquement en charge les relations d'égalité (ou l'inégalité lorsqu'elle est précédée de NOT ).
C'est un synonyme de = any / = some , eg
select *
from t1
where x in (select x from t2)
;
EXISTS prend en charge différents types de relations, qui ne peuvent pas être exprimées à l'aide de IN , par exemple -
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 || '℅'
)
;
Les prétendues performances et les différences techniques entre EXISTS et IN peuvent résulter d'implémentations / limitations / bogues spécifiques de fournisseurs, mais bien souvent, ce ne sont que des mythes créés en raison du manque de compréhension des bases de données internes.
La définition des tables, la précision des statistiques, la configuration de la base de données et la version de l'optimiseur ont tous un impact sur le plan d'exécution et donc sur les mesures de performance.
Le Exists
mot clé évalue vrai ou faux, mais le IN
mot clé compare toutes les valeurs dans la colonne de sous-requête correspondante. Un autre Select 1
peut être utilisé avec la Exists
commande. Exemple:
SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)
Mais IN
est moins efficace donc Exists
plus rapide.
Je pense,
EXISTS
c'est lorsque vous devez faire correspondre les résultats de la requête avec une autre sous-requête. Les résultats de la requête n ° 1 doivent être récupérés là où les résultats de la sous-requête correspondent. Type de jointure. Par exemple, sélectionnez le tableau des clients n ° 1 qui a également passé le tableau des commandes n ° 2
IN est à récupérer si la valeur d'une colonne spécifique se trouve dans IN
une liste (1, 2, 3, 4, 5).
Quand utiliser l'un par rapport à l'autre ... quand vous sentez qu'il se lit correctement (communique mieux l'intention).
La différence réside ici:
select *
from abcTable
where exists (select null)
La requête ci-dessus renverra tous les enregistrements tandis que celle ci-dessous retournera vide.
select *
from abcTable
where abcTable_ID in (select null)
Essayez-le et observez la sortie.
Laquelle est la plus rapide dépend du nombre de requêtes récupérées par la requête interne:
EXIST évalue sur vrai ou faux mais IN compare plusieurs valeurs. Lorsque vous ne savez pas que l'enregistrement existe ou non, vous devez choisir EXIST.
La raison en est que l'opérateur EXISTS fonctionne selon le principe «au moins trouvé». Il retourne vrai et arrête l'analyse du tableau une fois qu'au moins une ligne correspondante a été trouvée.
D'autre part, lorsque l'opérateur IN est combiné avec une sous-requête, MySQL doit d'abord traiter la sous-requête, puis utilise le résultat de la sous-requête pour traiter la requête entière.
La règle générale est que si la sous-requête contient un grand volume de données, l'opérateur EXISTS offre de meilleures performances.
Cependant, la requête qui utilise l'opérateur IN s'exécutera plus rapidement si l'ensemble de résultats renvoyé par la sous-requête est très petit.
Ma compréhension est que les deux devraient être les mêmes tant que nous n'avons pas affaire à des valeurs NULL.
La même raison pour laquelle la requête ne renvoie pas la valeur pour = NULL vs est NULL. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
En ce qui concerne l'argument booléen vs comparateur, pour générer un booléen, les deux valeurs doivent être comparées et c'est ainsi que fonctionne une condition, donc je n'arrive pas à comprendre comment IN et EXISTS se comportent différemment.
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
Si une sous-requête renvoie plusieurs valeurs, vous devrez peut-être exécuter la requête externe - si les valeurs de la colonne spécifiée dans la condition correspondent à n'importe quelle valeur du jeu de résultats de la sous-requête. Pour effectuer cette tâche, vous devez utiliser le in
mot - clé.
Vous pouvez utiliser une sous-requête pour vérifier si un ensemble d'enregistrements existe. Pour cela, vous devez utiliser la exists
clause avec une sous-requête. Le exists
mot clé renvoie toujours une valeur vraie ou fausse.
Je crois que cela a une réponse simple. Pourquoi ne le vérifiez-vous pas auprès des personnes qui ont développé cette fonction dans leurs systèmes?
Si vous êtes un développeur MS SQL, voici la réponse directement de Microsoft.
IN
:
Détermine si une valeur spécifiée correspond à une valeur d'une sous-requête ou d'une liste.
Spécifie une sous-requête pour tester l'existence de lignes.
J'ai trouvé que l'utilisation du mot clé EXISTS est souvent très lente (c'est très vrai dans Microsoft Access). J'utilise plutôt l'opérateur de jointure de cette manière: devrais-je-utiliser-le-mot-clé-existe-dans-sql
EXISTS est plus rapide en performances qu'en IN. Si la plupart des critères de filtrage sont dans la sous-requête, il vaut mieux utiliser IN et si la plupart des critères de filtrage sont dans la requête principale, il vaut mieux utiliser EXISTS.
Si vous utilisez l'opérateur IN, le moteur SQL analysera tous les enregistrements extraits de la requête interne. D'un autre côté, si nous utilisons EXISTS, le moteur SQL arrêtera le processus d'analyse dès qu'il trouvera une correspondance.
IN
et EXISTS
peuvent être équivalents et transformés les uns dans les autres.
JOIN
en remplacement deIN
.