2009-11-11 22 views
7

Ho due tabelle che voglio unire insieme usando un join esterno sinistro. Tuttavia, anche se la mia tabella di sinistra contiene solo valori univoci, la tabella di destra soddisfa la condizione più di una volta e, come tale, aggiunge ulteriori righe al gruppo di risultati.LEFT OUTER JOIN (dà righe aggiuntive) problema

Codice di replicare problema:

 
declare @tb1 table (c1 int) 
declare @tb2 table (c2 int) 

INSERT INTO @tb1 VALUES (1) 
INSERT INTO @tb1 VALUES (2) 
INSERT INTO @tb1 VALUES (3) 
INSERT INTO @tb1 VALUES (4) 

INSERT INTO @tb2 VALUES (3) 
INSERT INTO @tb2 VALUES (4) 
INSERT INTO @tb2 VALUES (5) 
INSERT INTO @tb2 VALUES (6) 

select * from @tb1 left outer join @tb2 ON c1 = c2 

INSERT INTO @tb2 VALUES (3) 
INSERT INTO @tb2 VALUES (4) 
INSERT INTO @tb2 VALUES (5) 
INSERT INTO @tb2 VALUES (6) 

select * from @tb1 left outer join @tb2 ON c1 = c2 

Come si può vedere le prime dichiarazioni selezionare 4 righe, in cui la seconda selezionate 6, anche se la tabella di sinistra rimane invariato.

Come si rimane rigorosi sul tavolo sinistro e si utilizza solo la tabella di destra per COMPLEMENTARE le righe dal tavolo sinistro?

AIUTO!

 
RESULTS: 
c1   c2 
----------- ----------- 
1   NULL 
2   NULL 
3   3 
4   4 

[DUPLICATE @tb2 records] 

c1   c2 
----------- ----------- 
1   NULL 
2   NULL 
3   3 
3   3 
4   4 
4   4 
+0

Ho una tabella con più righe non distinte (log di login) la mia tabella di sinistra è questa tabella raggruppata per ID utente, quindi è distinta. la tabella di destra è la tabella originale, che contiene i dati di cui ho bisogno. Quindi collego la tabella di destra alla tabella di sinistra usando USERid, in modo che possa restituire i dati utili –

risposta

10

Scusa, ma il tuo pensiero è distorto.

Pensateci in questo modo: se volete una sola riga da tb2 per ogni riga in tb1, quale deve scegliere il server? Il fatto è che dalla definizione di un join, ogni riga nella tabella sul lato destro che corrisponde alla riga del lato sinistro è una corrispondenza e deve essere inclusa.

È necessario assicurarsi che tbl2 abbia valori distinti per c2 prima del join. Il suggerimento di Murph potrebbe farlo, a condizione che la tua variante SQL supporti DISTINCT [colonna] (non tutti lo fanno).

+0

Sì, ne avevo paura. –

+0

Questo era assolutamente giusto, e in quanto tale ho modificato il mio modo di pensare e quindi la mia dichiarazione ON per essere unica, alleviando il problema. –

+0

Sembra che il join esterno sinistro restituisca righe distinte su sqlite per lo stesso esempio! non so perché. Facendo un 'select distinct ...' come per il suggerimento @astander risolve quel problema. – Pykler

3

selezionare distinta * da @ tb1 sinistra outer join @ tb2 ON c1 = c2

+0

Da 100 ms di ESECUZIONE, questo scatto fino a 83 secondi. –

+0

Hai bisogno di fornirci maggiori dettagli su cosa stai cercando di ottenere – Murph

+0

Quanto è grande la tabella che impiega 83 secondi? Stai usando l'operatore LIKE nella tua domanda reale? – invert

4

Prova useing

select DISTINCT * from @tb1 left outer join @tb2 ON c1 = c2 
+0

Ciò funzionerebbe in questo caso semplificato, ma sono abbastanza sicuro che in realtà la sua tabella rhs ha più colonne, e quindi non distingue. –

+0

Sono d'accordo, e in quel caso poi ha bisogno di decidere cosa rende la riga "distinta", o dovrà visualizzare più righe con l'id dalla tabella 1 –

+0

per quanto riguarda selezionare distinto su (col, col) – xenoterracide

3

Se si desidera mantenere solo singoli file sul lato sinistro, si Dovrai decidere cosa vuoi mostrare sulla destra, per ogni valore unico sulla sinistra. Se si desidera mostrare un conteggio, per esempio, si potrebbe fare questo:

select b1.c1, x.c from @tb1 b1 
left outer join 
(
    select c2, count(*) as c 
    from @tb2 
    group by c2 
) as x 
ON b1.c1 = x.c2 

o se volete solo un'occorrenza di valori da c2:

select b1.c1, x.c2 from @tb1 b1 
left outer join 
(
    select c2 
    from @tb2 
    group by c2 
) as x 
ON b1.c1 = x.c2 
+0

L'esempio sopra è solo un esempio, e come tale ogni tabella ha solo una colonna. –

+0

grazie per questa risposta. Mi unisco a 5 tavoli con record> 250K e questa risposta era esattamente ciò di cui avevo bisogno. – TMG

+0

questo è stato molto utile – AFD

2

Hmm, la query viene a fare ciò che il suo supposto perché ci sono record duplicati (o almeno identificatori duplicati) nella tabella di destra.

per ottenere l'effetto che si desidera qualcosa di simile:

SELECT * FROM @tb1 LEFT OUTER JOIN (SELECT DISTINCT c2 FROM @tb2) t2 ON @tb1.c1 = t2.c2 

Se questo non è sufficiente è necessario spiegare il requisito di cui un po 'più in dettaglio.