SQL Server Left Join Avec 'Ou' Opérateur
J'ai un quatre tables, TopLevelParent, deux de niveau moyen tables MidParentA et MidParentB, et une table d'Enfant qui peut avoir un parent de MidParentA ou MidParentB (l'Un ou l'autre midParent doivent être en place). Les deux mi-hauteur des tables ont un parent, un tableau de TopLevelParent.
Le Haut Niveau de la table ressembler à ceci:
TopLevelId | Name
--------------------------
1 | name1
2 | name2
La MidParent tables ressembler à ceci:
MidParentAId | TopLevelParentId | MidParentBId | TopLevelParentId |
------------------------------------ ------------------------------------
1 | 1 | 1 | 1 |
2 | 1 | 2 | 1 |
La table Enfant ressembler à ceci:
ChildId | MidParentAId | MidParentBId
--------------------------------
1 | 1 | NULL
2 | NULL | 2
J'ai utilisé les suivants jointure gauche dans un plus grand procédure stockée qui est du timing, et il semble que l'opérateur OU sur la dernière jointure gauche est coupable:
SELECT *
FROM TopLevelParent tlp
LEFT JOIN MidParentA a ON tlp.TopLevelPatientId = a.TopLevelPatientId
LEFT JOIN MidParentB a ON tlp.TopLevelPatientId = b.TopLevelPatientId
LEFT JOIN Child c ON c.ParentAId = a.ParentAId OR c.ParentBId = b.ParentBId
Est-il plus performant façon de le faire adhérer?
bonne question + bonnes réponses
OriginalL'auteur Declan McNulty | 2013-11-01
Vous devez vous connecter pour publier un commentaire.
Compte tenu du peu de la requête est en cours d'exposé; un très approximative de la règle de base est de remplacer un Ou avec un Syndicat pour éviter table de numérisation.
Cela aide 🙂 Vous pourriez avoir deux se joint à l'Enfant plutôt que de le un chacun de faire un côté de la OU; et ensuite utiliser fusionner pour obtenir une valeur de C ou D où vous voulez seulement une valeur
OriginalL'auteur u07ch
Vous devez prendre soin de l'aide de prédicats de l'intérieur.
"Il est très important de comprendre que, avec les jointures externes, et OÙ l'une des clauses de jouer des rôles très différents, et par conséquent, ils ne sont pas interchangeables. La clause where joue encore un filtrage simple de rôle à savoir, il conserve les vraies affaires et des rejets de faux et de cas inconnus. Utiliser quelque chose comme cela et l'utilisation des prédicats dans la clause where. Toutefois, la clause ne joue pas un simple filtrage de rôle; plutôt, c'est plus une correspondance de rôle. En d'autres termes, une ligne dans le préservée côté sera retourné si le prédicat trouve une correspondance pour elle ou pas. Si le prédicat seulement détermine les lignes de la nonpreserved côté sont accompagnés de lignes de la préservés côté—pas de possibilité de retourner les lignes de la conserves de côté." **Examen 70-461: Requêtes Microsoft SQL Server 2012
OriginalL'auteur Amir Keshavarz
Voici ce que j'ai fait en fin de compte, qui a obtenu le temps d'exécution vers le bas à partir de 52 secondes à 4 secondes.
Ceci élimine le tableau de numérisation qui se passait, comme je l'ai assorti le haut niveau d'enregistrement à son midlevel assurant parent à l'avant si elle existe, et marqué sur l'album.
J'ai également fait la même chose avec l'enfant d'enregistrer ce qui signifie que je peux simplement rejoindre l'enfant, l'enregistrement vers le haut niveau d'enregistrement sur le MidParentId, et j'utilise le IsMidParentA bit indicateur de différencier où il y a deux identiques MidParentIds (c'est à dire un Id de 1 pour IsMidParentA et IsMidParentB).
Merci à tous ceux qui ont pris le temps de répondre.
les choses dégénèrent rapidement
OriginalL'auteur Declan McNulty
une autre façon de l'écrire:
LEFT JOIN Child c ON c.ParentAId = COALESCE(a.ParentAId, b.ParentBId)
Modifier
Une approche possible est l'interrogation première de la MidParentA et puis le MidParentB et puis
UNION
les résultats:Une démo en SQLFiddle
vous avez raison, à première vue, je n'ai pas lu attentivement la question
OriginalL'auteur mucio