web-dev-qa-db-fra.com

Comment un LEFT OUTER JOIN peut-il renvoyer plus d'enregistrements qu'il n'en existe dans la table de gauche?

J'ai un très basique LEFT OUTER JOIN pour renvoyer tous les résultats de la table de gauche et quelques informations supplémentaires d'une table beaucoup plus grande. La table de gauche contient 4935 enregistrements. Cependant, lorsque I LEFT OUTER JOIN est associée à une table supplémentaire, le nombre d’enregistrements est considérablement plus important.

Autant que je sache, l'évangile absolu est qu'un LEFT OUTER JOIN renvoie tous les enregistrements de la table de gauche avec les enregistrements correspondants de la table de droite et des valeurs null pour toutes les lignes qui ne peuvent pas être identiques. Par conséquent, je pense qu'il devrait être impossible de retourner plus de lignes qu'il n'en existe dans la table de gauche, mais ça se passe quand même!

La requête SQL suit:

SELECT     SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM         SUSP.Susp_Visits LEFT OUTER JOIN
                      DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum

J'ai peut-être commis une erreur de syntaxe ou ma compréhension de LEFT OUTER JOIN est incomplète. J'espère que quelqu'un pourra expliquer comment cela pourrait se produire.

Postscript

Merci pour les bonnes réponses, ma compréhension de LEFT OUTER JOINS est maintenant bien meilleure. Quelqu'un pourrait-il toutefois suggérer de modifier cette requête de manière à ne recevoir que le nombre d’enregistrements renvoyés dans le tableau de gauche?

Cette requête est purement destinée à générer un rapport et les doublons correspondent à une confusion.

/ Postscript

140
Jay Wilde

LEFT OUTER JOIN renvoie tous les enregistrements de la table LEFT jointe à la table RIGHT dans la mesure du possible.

Cependant, s'il y a des correspondances, toutes les lignes correspondantes seront renvoyées. Par conséquent, une ligne LEFT qui correspond à deux lignes RIGHT retournera sous la forme de deux ROWS, tout comme un INNER JOIN.

EDIT: En réponse à votre modification, je viens d’examiner de plus près votre requête et il semblerait que vous ne renvoyiez que des données de la table LEFT. Par conséquent, si vous souhaitez uniquement des données de la table LEFT et qu'une seule ligne est renvoyée pour chaque ligne de la table LEFT, vous n'avez alors pas besoin de réaliser une JOIN, mais vous pouvez simplement effectuer une commande SELECT directement à partir de la table LEFT.

158
Robin Day
Table1                Table2
_______               _________
1                      2
2                      2
3                      5
4                      6

SELECT Table1.Id, Table2.Id FROM Table1 LEFT OUTER JOIN Table2 ON Table1.Id=Table2.Id

Résultats:

1,null
2,2
2,2
3,null
4,null
98
Andrew Lewis

Ce n'est pas impossible. Le nombre d'enregistrements dans la table de gauche est le nombre minimal d'enregistrements qu'il retournera. Si la table de droite a deux enregistrements correspondant à un enregistrement dans la table de gauche, deux enregistrements seront renvoyés.

30
HLGEM

En réponse à votre post-scriptum, cela dépend de ce que vous souhaitez.

Vous obtenez (possible) plusieurs lignes pour chaque ligne de votre table de gauche car il existe plusieurs correspondances pour la condition de jointure. Si vous souhaitez que le total de vos résultats contienne le même nombre de lignes que dans la partie gauche de la requête, vous devez vous assurer que vos conditions de jointure entraînent une correspondance 1 pour 1.

Vous pouvez également utiliser des fonctions d'agrégat en fonction de vos souhaits (par exemple, si vous souhaitez simplement une chaîne de la partie droite, vous pouvez générer une colonne qui est une chaîne délimitée par des virgules des résultats situés à droite de la ligne de gauche.

Si vous ne regardez que 1 ou 2 colonnes de la jointure externe, vous pouvez envisager d'utiliser une sous-requête scalaire, car vous aurez 1 résultat garanti.

10

Chaque enregistrement de la table de gauche sera renvoyé autant de fois qu'il y a d'enregistrements correspondants dans la table de droite - au moins 1, mais peut facilement en contenir plus de 1.

8
Alex Martelli

LEFT OUTER JOIN exactement comme INNER JOIN (jointure normale) renverra autant de résultats pour chaque ligne de la table de gauche que de correspondances trouvées dans la table de droite. Par conséquent, vous pouvez avoir beaucoup de résultats - jusqu'à N x M, où N est le nombre de lignes du tableau de gauche et M le nombre de lignes du tableau de droite.

C'est que le nombre minimum de résultats est toujours garanti dans LEFT OUTER JOIN égal à au moins N.

7
topchef

Pourrait-il s'agir d'une relation un à plusieurs entre les tables gauche et droite?

6
Ken Burkhardt

Faites attention si vous avez une clause where sur le tableau "du côté droit" d'une requête contenant une jointure externe gauche ... Si vous n'avez aucun enregistrement du côté droit satisfaisant la clause where, alors l'enregistrement correspondant du "côté gauche" 'table n'apparaîtra pas dans le résultat de votre requête ....

6
Serge

Si vous avez besoin de n'importe quelle ligne du côté droit

SELECT SuspReason, SiteID FROM(
    SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER()
    OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn
    FROM SUSP.Susp_Visits
    LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
) AS t
WHERE rn=1

ou juste

SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID
FROM SUSP.Susp_Visits WHERE EXISTS(
    SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum
)
4
A-K

Il semble qu'il y ait plusieurs lignes dans la table DATA.Dim_Member par ligne SUSP.Susp_Visits.

1
bdukes

si plusieurs (x) lignes dans Dim_Member sont associées à une seule ligne dans Susp_Visits, il y aura x lignes dans le résultat.

1
Manu