Come può un LEFT OUTER JOIN restituire più record di quelli presenti nella tabella di sinistra?


165

Ho un JOIN ESTERNO SINISTRA molto semplice per restituire tutti i risultati dalla tabella di sinistra e alcune informazioni aggiuntive da una tabella molto più grande. La tabella di sinistra contiene 4935 record ma quando ho lasciato ESTERNO UNISCITI a una tabella aggiuntiva il conteggio dei record è significativamente maggiore.

Per quanto ne so, è assolutamente vangelo che un JOIN ESTERNO SINISTRO restituirà tutti i record della tabella di sinistra con i record corrispondenti della tabella di destra e valori nulli per tutte le righe che non possono essere abbinate, in quanto tale intendo che dovrebbe essere impossibile restituire più righe di quelle esistenti nella tabella di sinistra, ma sta succedendo lo stesso!

Query SQL segue:

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

Forse ho fatto un errore nella sintassi o la mia comprensione di LEFT OUTER JOIN è incompleta, si spera che qualcuno possa spiegare come ciò potrebbe accadere?

poscritto

Grazie per le ottime risposte, la mia comprensione di LEFT OUTER JOINS è ora molto migliore, qualcuno potrebbe comunque suggerire un modo in cui questa query potrebbe essere modificata in modo da ottenere solo quanti record restituiti esistono nella tabella a sinistra?

Questa query serve esclusivamente a generare un rapporto e le corrispondenze duplicate confondono semplicemente le cose.

/ Postscript


5
Per "ottenere tutti i record restituiti presenti nella tabella di sinistra", devi specificare quale riga dal lato destro scegliere se ci sono più corrispondenze.
AK,

1
come lo specifichi? Vorrei che la prima partita venisse restituita.
Simon Cross,

1
devi definire cosa si intende per primo incontro. Vuoi il primo record, quello con l'ID più alto o cosa?
HLGEM,

1
Se si abbina con la chiave primaria nella tabella aggiuntiva, l'istruzione è corretta.
Prageeth godage

Uso spesso una risorsa come questa come cheat sheet quando costruisco query. Se il collegamento dovesse mai scomparire, basta unirsi a google sql ; sono diagrammi di Venn dei diversi tipi di join.
Zimano,

Risposte:


190

L'UNIONE ESTERNA SINISTRA restituirà tutti i record dalla tabella SINISTRA unita alla tabella DESTRA laddove possibile.

Se tuttavia ci sono corrispondenze, verranno comunque restituite tutte le righe corrispondenti, pertanto una riga in SINISTRA che corrisponde a due righe in DESTRA restituirà due righe, proprio come un INNER JOIN.

EDIT: in risposta alla tua modifica, ho appena dato un'occhiata alla tua query e sembra che tu stia solo restituendo i dati dalla tabella LEFT. Pertanto, se si desidera solo i dati dalla tabella SINISTRA e si desidera restituire solo una riga per ogni riga nella tabella SINISTRA, non è necessario eseguire un JOIN e si può semplicemente eseguire una SELEZIONA direttamente dalla tabella SINISTRA.


1
Il motivo per cui mi sono unito al tavolo giusto è stato quindi ho ottenuto solo i record da sinistra dove c'era almeno un record nel tavolo giusto, ma grazie mille per la spiegazione.
Jay Wilde,

125
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

risultati:

1,null
2,2
2,2
3,null
4,null

1
Così semplice, eppure così potente.
Kiradotee,

39

Non è impossibile Il numero di record nella tabella di sinistra è il numero minimo di record che restituirà. Se la tabella di destra ha due record che corrispondono a un record nella tabella di sinistra, restituirà due record.


12

In risposta al tuo poscritto, dipende da cosa vorresti.

Stai ottenendo (possibili) più righe per ogni riga nella tabella di sinistra perché ci sono più corrispondenze per la condizione di join. Se si desidera che i risultati totali abbiano lo stesso numero di righe presente nella parte sinistra della query, è necessario assicurarsi che le condizioni del join causino una corrispondenza 1 a 1.

In alternativa, a seconda di ciò che si desidera effettivamente è possibile utilizzare le funzioni di aggregazione (se ad esempio si desidera solo una stringa dalla parte destra, è possibile generare una colonna che è una stringa delimitata da virgole dei risultati del lato destro per quella riga sinistra.

Se stai guardando solo 1 o 2 colonne dal join esterno, potresti prendere in considerazione l'utilizzo di una subquery scalare poiché ti garantirà 1 risultato.


4
Questa è una buona risposta poiché offre suggerimenti su come restituire solo le righe dalla tabella di sinistra.
karns

9

Ogni record dalla tabella di sinistra verrà restituito tutte le volte che ci sono record corrispondenti nella tabella di destra - almeno 1, ma potrebbe facilmente essere più di 1.


8

LEFT OUTER JOIN, proprio come INNER JOIN (join normale) restituirà tutti i risultati per ogni riga nella tabella di sinistra quante corrispondenze trova nella tabella di destra. Quindi puoi avere molti risultati - fino a N x M, dove N è il numero di righe nella tabella di sinistra e M è il numero di righe nella tabella di destra.

È il numero minimo di risultati è sempre garantito in LEFT OUTER JOIN per essere almeno N.


1
Ho iniziato a pensare quando il numero di righe è uguale a N x M e l'unica situazione reale che mi viene in mente è quando N o M è uguale a 1. Sei d'accordo?
BartoszMiller,

2
No, non lo so. Non dovresti pensare alla condizione di join solo come join di uguaglianza chiave. Può essere una condizione arbitraria, ad es. Intervalli di date, disuguaglianze, ecc. Due casi estremi: (a) N righe non hanno una singola corrispondenza tra M righe, quindi i risultati del join esterno sinistro in N righe corrispondenti a NULL. (b) ciascuna delle N righe corrisponde a tutte le M righe, quindi il risultato è N x M righe impostate.
topchef,

1
Hai ragione, stavo pensando di unirmi solo in termini di uguaglianza chiave. Mi piace il tuo esempio dal "caso b". Credo che "ognuna delle N righe corrisponda a tutte le M righe" è una ricetta generale per quando vengono restituite le righe N x M, il che è piuttosto impossibile da visualizzare quando si pensa solo all'uguaglianza chiave.
BartoszMiller,

7

Potrebbe essere una o più relazioni tra la tabella di sinistra e quella di destra?


6

Prestare attenzione se si dispone di una clausola where nella tabella "lato destro" di una query contenente un join esterno sinistro ... Nel caso in cui non vi siano record sul lato destro che soddisfino la clausola where, quindi il record corrispondente del lato sinistro 'tabella non verrà visualizzata nel risultato della query ....


1
È quindi necessario aggiungere la condizione alla clausola ON del corrispondente LEFT OUTER JOIN.
Mik,

6

Se hai bisogno di una sola riga dal lato destro

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

o solo

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
)

1
Poiché non hai fornito DDL e DML, non ho eseguito il test. Comunque penso che EXISTS sia quello che vuoi. Prova questo: SELEZIONA SuspReason, SiteID FROM (SELEZIONA SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER () OVER (PARTITION BY SUSP.Susp_Visits.SiteID ORDER BY SUSP.Susp_Visits.SiteID) AS rn FROM SUSP.SpS_SUSP ISCRIVITI DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum) COME tnERE rn = 1
AK

2

Sembra che ci siano più righe nella tabella DATA.Dim_Member per riga SUSP.Susp_Visits.


2

se più (x) righe in Dim_Member sono associate a una singola riga in Susp_Visits, nel set di risultati saranno presenti x righe.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.