Je dois implémenter la requête suivante dans SQL Server:
select *
from table1
WHERE (CM_PLAN_ID,Individual_ID)
IN
(
Select CM_PLAN_ID, Individual_ID
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
)
Mais la clause WHERE..IN n'autorise qu'une seule colonne. Comment puis-je comparer 2 colonnes ou plus avec un autre SELECT interne?
sql-server
ala
la source
la source
Réponses:
Vous pouvez créer une table dérivée à partir de la sous-requête et joindre table1 à cette table dérivée:
la source
Vous voudrez plutôt utiliser la syntaxe WHERE EXISTS.
la source
AVERTISSEMENT CONCERNANT LES SOLUTIONS:
DE NOMBREUSES SOLUTIONS EXISTANTES DONNERONT UNE FAUTE SORTIE SI LES RANGÉES NE SONT PAS UNIQUES
Si vous êtes la seule personne à créer des tables, cela peut ne pas être pertinent, mais plusieurs solutions donneront un nombre de lignes de sortie différent du code en question, lorsque l'une des tables peut ne pas contenir de lignes uniques.
AVERTISSEMENT CONCERNANT L'ÉNONCÉ DU PROBLÈME:
IN AVEC PLUSIEURS COLONNES N'EXISTE PAS, PENSEZ ATTENTIVEMENT CE QUE VOUS VOULEZ
Quand je vois un in avec deux colonnes, je peux l'imaginer pour signifier deux choses:
Le scénario 1 est assez trivial, utilisez simplement deux instructions IN.
Conformément à la plupart des réponses existantes, je donne ici un aperçu des approches mentionnées et supplémentaires pour le scénario 2 (et un bref jugement):
EXISTS (sûr, recommandé pour SQL Server)
Tel que fourni par @mrdenny, EXISTS sonne exactement comme ce que vous recherchez, voici son exemple:
LEFT SEMI JOIN (Safe, recommandé pour les dialectes qui le supportent)
C'est une manière très concise de rejoindre, mais malheureusement, la plupart des dialectes SQL, y compris le serveur SQL, ne le prennent pas actuellement en charge.
Plusieurs instructions IN (sûr, mais attention à la duplication de code)
Comme mentionné par @cataclysm, l'utilisation de deux instructions IN peut également faire l'affaire, peut-être même qu'elle surpassera les autres solutions. Cependant, vous devez faire très attention à la duplication de code. Si vous souhaitez effectuer une sélection dans une autre table ou modifier l'instruction where, vous risquez davantage de créer des incohérences dans votre logique.
Solution basique
Solution sans duplication de code (je pense que cela ne fonctionne pas dans les requêtes SQL Server régulières)
INNER JOIN (techniquement, cela peut être sécurisé, mais souvent cela n'est pas fait)
La raison pour laquelle je ne recommande pas d'utiliser une jointure interne comme filtre, c'est qu'en pratique, les gens laissent souvent les doublons dans la table de droite provoquer des doublons dans la table de gauche. Et puis, pour aggraver les choses, ils rendent parfois le résultat final distinct alors que la table de gauche n'a peut-être pas besoin d'être unique (ou pas unique dans les colonnes que vous sélectionnez). De plus, cela vous donne la possibilité de sélectionner une colonne qui n'existe pas dans le tableau de gauche.
Erreurs les plus courantes:
CONCATENATION DE COLONNES AVEC SEPARATEUR (Pas très sûr, performances horribles)
Le problème fonctionnel est que si vous utilisez un séparateur qui pourrait apparaître dans une colonne, il devient difficile de s'assurer que le résultat est précis à 100%. Le problème technique est que cette méthode entraîne souvent des conversions de type et ignore complètement les index, ce qui entraîne des performances potentiellement horribles. Malgré ces problèmes, je dois admettre que je l'utilise encore parfois pour des requêtes ad hoc sur de petits ensembles de données.
Notez que si vos colonnes sont numériques, certains dialectes SQL vous demanderont d'abord de les convertir en chaînes. Je crois que le serveur SQL le fera automatiquement.
Pour résumer les choses: comme d'habitude, il existe de nombreuses façons de faire cela en SQL, utiliser des choix sûrs évitera les surprises et vous fera gagner du temps et de la tête à long terme.
la source
Remarque:
Oracle ignore les lignes où une ou plusieurs des colonnes sélectionnées sont NULL. Dans ces cas, vous voudrez probablement utiliser NVL -Funktion pour mapper NULL à une valeur spéciale (qui ne devrait pas être dans les valeurs);
la source
where (colA,colB) in (... some list of tuples...)
mais je ne suis pas sûr de ce que les autres bases de données font de même. Je serais intéressé de savoir.Une simple clause EXISTS est la plus propre
Si vous avez plusieurs lignes dans la corrélation, un JOIN donne plusieurs lignes dans la sortie, vous aurez donc besoin de distinctes. Ce qui rend généralement les EXISTS plus efficaces.
La note
SELECT *
avec un JOIN inclurait également les colonnes des tables de limitation de lignela source
Pourquoi utiliser WHERE EXISTS ou DERIVED TABLES lorsque vous pouvez simplement faire une jointure interne normale:
Si la paire de (CM_PLAN_ID, Individual_ID) n'est pas unique dans la table d'état, vous aurez peut-être besoin d'un SELECT DISTINCT t. * À la place.
la source
1.Utilisation avec
EXISTS
[Temps de requête moyen: 1,42 s]2. Utilisation de la clause avec deux lignes
IN
[Temps de requête moyen: 0,37 s]3.Utilisation avec un
INNNER JOIN
modèle [Temps de requête moyen: 2,9 s]Alors, j'ai choisi la deuxième option.
la source
AND
déclarations plutôt que desOR
déclarations.OR
déclaration soulève probablement des doublons. Dans mon cas, il n'y a aucune ligne qui contient la même chosesrc_id
etdest_id
sur une seule ligne. Donc, les duplications ne se produiront pas dans mon cas.Requete:
la requête ci-dessus a fonctionné pour moi dans mysql. se référer au lien suivant ->
https://www.w3resource.com/sql/subqueries/multiplee-row-column-subqueries.php
la source
Si vous voulez une table, utilisez la requête suivante
et les données du tableau comme suit
Puis sortie comme suit
la source
id in (1,2) and studentName in ('a','b')
est totalement différent de(id, studentName) in ((1,'a'),(2,'b'))
. Pensez simplement à un enregistrement ayant id = 2 et name = 'a'. Bien sûr, si l'ID est unique, l'effet est diminué, mais ensuite, si l'ID est unique, nous n'avons pas du tout besoin de filtrer les noms.Nous pouvons simplement le faire.
la source
Concaténer les colonnes ensemble sous une forme ou une autre est un "hack", mais lorsque le produit ne prend pas en charge les semi-jointures pour plus d'une colonne, vous n'avez parfois pas le choix.
Exemple où la solution de jointure interne / externe ne fonctionnerait pas:
Lorsque les requêtes ne sont pas de nature triviale, vous n'avez parfois pas accès à l'ensemble de table de base pour effectuer des jointures internes / externes régulières.
Si vous utilisez ce "hack", lorsque vous combinez des champs, assurez-vous simplement d'ajouter suffisamment de délimiteur entre eux pour éviter les erreurs d'interprétation, par exemple
ColA + ":-:" + ColB
la source
J'ai fondé plus facilement de cette façon
J'espère que cette aide :)
la source
CM_PLAN_ID = 45
etIndividual_ID = 3
ensuite la concaténation aboutit453
- ce qui est impossible à distinguer du cas oùCM_PLAN_ID = 4
etIndividual_ID = 53
... demander des ennuis, j'aurais pensé45_3
ou45:3
mais ce n'est toujours pas une bonne solution et bien sûr comme @mrdenny dit que les index ne seront plus utilisés maintenant qu'une transformation a eu lieu sur les colonnes.Une manière simple et incorrecte serait de combiner deux colonnes en utilisant + ou de concaténer et de créer une colonne.
Ce serait bien sûr assez lent. Ne peut pas être utilisé dans la programmation, mais si dans le cas où vous demandez juste pour vérifier quelque chose peut être utilisé.
la source