Left join

martedì 20 gennaio 2009 - 18.41

Davide.70 Profilo | Newbie

Ho due tabelle e sto tentando di fare il left join della prima con la seconda. Per qualche strano motivo,
il risultato della query ha meno record di quelli della prima tabella, mentre mi aspettavo che me li restituisse
tutti:

SELECT OorP.itemnumber, dbo_FS_BillOfMaterial.ComponentItemNumber
FROM OorP LEFT JOIN dbo_FS_BillOfMaterial ON OorP.itemkey = dbo_FS_BillOfMaterial.ParentItemKey
WHERE (((dbo_FS_BillOfMaterial.ComponentItemNumber) Like 'S_*') and dbo_FS_BillOfMaterial.ComponentType='T');

la tabella OorP ha 4409 record, la query solo 3911. In effetti se verifico gli ItemNumber della prima tabella
che sono NOT IN risultato ottengo 498 record.
Che ne pensate? grazie,

Davide

lbenaglia Profilo | Guru

>SELECT OorP.itemnumber, dbo_FS_BillOfMaterial.ComponentItemNumber
>FROM OorP LEFT JOIN dbo_FS_BillOfMaterial ON OorP.itemkey = dbo_FS_BillOfMaterial.ParentItemKey
>WHERE (((dbo_FS_BillOfMaterial.ComponentItemNumber) Like 'S_*')
>and dbo_FS_BillOfMaterial.ComponentType='T');
>
>la tabella OorP ha 4409 record, la query solo 3911. In effetti
>se verifico gli ItemNumber della prima tabella
>che sono NOT IN risultato ottengo 498 record.

Ciao Davide,

Stai specificando una clausola WHERE sulle colonne della seconda tabella, pertanto ti verranno restituite SOLO le righe che soddisfano quella condizione (ignorando quindi le righe della seconda tabella valorizzate a NULL per via della LEFT OUTER JOIN).
Per ottenere anche quelle dovrai aggiungere la condizione OR dbo_FS_BillOfMaterial.<colonna primary key> IS NULL.

> grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

alx_81 Profilo | Guru

Ciao e benvenuto su dotnethell!

>la tabella OorP ha 4409 record, la query solo 3911. In effetti
>se verifico gli ItemNumber della prima tabella
>che sono NOT IN risultato ottengo 498 record.
>Che ne pensate?
Ma scusa, la where ridurrà il numero di righe no? è del tutto normale..
senza where di sicuro avrai tutti i record della prima tabella (o meglio quella di sinistra), ma quella where riduce le righe di quei record che ti trovi nella not in successiva.

>grazie,
di nulla!

--

Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

Davide.70 Profilo | Newbie

Grazie a tutti per l'aiuto. Purtroppo però continuo ad avere meno record di quelli attesi. Il problema potrebbe essere correlato al fatto che per il join io non uso la primary key della tabella B:

SELECT OorP.*, dbo_FS_BillOfMaterial.ComponentItemNumber
FROM OorP LEFT JOIN dbo_FS_BillOfMaterial ON OorP.ItemKey=dbo_FS_BillOfMaterial.ParentItemKey
WHERE ((dbo_FS_BillOfMaterial.ComponentItemNumber Like 'S_*' AND dbo_FS_BillOfMaterial.ComponentType='T') OR dbo_FS_BillOfMaterial.ParentItemKey IS NULL);

Ho aggiunto la condizione IS NULL, applicandola sia alla chiave primaria BillOfMaterialKey , che è un contatore, sia al campo di join ParentItemKey ed anche a ComponentItemNumber . In tutti e tre i casi ottengo 3934 record, anziche gli attesi 4409 della tabella A. Suggerimenti?
Grazie mille,
Davide


Davide.70 Profilo | Newbie

Altra cosa, vorrei un chiarimento sulla risposta. Un record non può avere chiave nulla, quindi cosa cambierebbe?
non mi torna... grazie,

Davide

lbenaglia Profilo | Guru

>Altra cosa, vorrei un chiarimento sulla risposta. Un record non
>può avere chiave nulla, quindi cosa cambierebbe?
>non mi torna... grazie,
Quando esegui una left outer join, le colonne della tabella dalla parte molti della relazione (destra) che non hanno una corrispondenza nella tabella dalla parte uno della relazione (sinistra) verranno valorizzate a NULL (PK compresa).

Ora, se vuoi ricevere un aiuto mirato posta un esempio semplificato della tua situazione con le CREATE TABLE, alcune righe di prova (INSERT INTO) ed il result set atteso.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

Grazie Lorenzo,
ma forse non mi sono spiegato bene. E' nella tabella sx che ci sono più record. Sono quelli che non appaiono nel risultato finale, perchè non hanno corrispondenti nella tabella dx. Pensavo che un left join risolvesse, ma in effetti imponendo una condizione Where i record della tabella sx che non hanno corrispondenti nella tabella dx che soddisfano la condizione restano esclusi.
Ora io vorrei sia i record della tabella sx che soddifano la condizione sia gli altri che non la soddisfano.
Grazie e scusate l'ignoranza :-)
Davide

lbenaglia Profilo | Guru

>E' nella tabella sx che ci
>sono più record. Sono quelli che non appaiono nel risultato finale,
>perchè non hanno corrispondenti nella tabella dx. Pensavo che
>un left join risolvesse, ma in effetti imponendo una condizione
>Where i record della tabella sx che non hanno corrispondenti
>nella tabella dx che soddisfano la condizione restano esclusi.
>Ora io vorrei sia i record della tabella sx che soddifano la
>condizione sia gli altri che non la soddisfano.
Si questo lo avevamo capito, ma un esempio completo ti assicuro che serve moltissimo a comprendere un problema nel complesso
"Brancolando nel buio" prova a spostare le condizioni espresse nella clausola WHERE nella clausola ON:

SELECT OorP.itemnumber, dbo_FS_BillOfMaterial.ComponentItemNumber FROM OorP LEFT JOIN dbo_FS_BillOfMaterial ON OorP.itemkey = dbo_FS_BillOfMaterial.ParentItemKey AND dbo_FS_BillOfMaterial.ComponentItemNumber Like 'S_*' AND dbo_FS_BillOfMaterial.ComponentType='T';

In questo modo il filtraggio verrà applicato prima di eseguire la JOIN e non sul result set risultante.

>Grazie e scusate l'ignoranza :-)
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

Graazie mille Lorenzo, logicamente funziona. Purtroppo però quando la applico alla tabella vera e propria (e non a OorP che è una select sui dati della tabella) Access 2003 sp3 va in crash:

"MS Access has encountered a problem and needs to close. We are sorry for the inconvinience"

Ho riprovato più volte ed ottengo sempre lo stesso errore... Idee? grazie ancora,
Davide

Davide.70 Profilo | Newbie

Per maggior chiarezza vi posto la query completa:

SELECT dbo_FS_Item.ItemNumber, dbo_FS_Item.ItemReference5, dbo_FS_Item.ItemDescription, dbo_FS_Item.ItemStatus, dbo_FS_Item.ItemClass1, dbo_FS_BillOfMaterial.ComponentItemNumber
FROM dbo_FS_Item LEFT JOIN dbo_FS_BillOfMaterial ON (dbo_FS_Item.itemkey = dbo_FS_BillOfMaterial.ParentItemKey
AND (dbo_FS_Item.ItemStatus='P' OR dbo_FS_Item.ItemStatus='O')
AND dbo_FS_BillOfMaterial.ComponentItemNumber Like 'S_*'
AND dbo_FS_BillOfMaterial.ComponentType='T');

1. Access toglie le parentesi dopo l'ON del join , quando apro la query in design , ma sei poi la eseguo senza parentesi dà errore di sintassi;

2. se invece rimetto, come giusto, le parentesi, genera l'errore che vi dicevo, va in crash e si chiude.

Le tabelle provengono da un'origine dati esterna, un dababase SQL, tramite connessione ODBC.
Come posso fare per mostrarvele? grazie mille,

Davide

lbenaglia Profilo | Guru

>Le tabelle provengono da un'origine dati esterna, un dababase
>SQL, tramite connessione ODBC.
>Come posso fare per mostrarvele? grazie mille,

Importale in un nuovo mdb, zippalo ed allegalo ad un nuovo messaggio.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

Ok. Ho però messo solo alcuni record di esempio (erano una infinità!). Rieseguendo la query famigerata (ArtStamp2) questa volta viene mostrato un altro msg di errore: "Join non supportato", anche se poi un risultato lo dà (??).
In allegato c'è il file. Grazie,

Davide

lbenaglia Profilo | Guru

>In allegato c'è il file.
A me questa va:

SELECT OorP.itemnumber, dbo_FS_BillOfMaterial.ComponentItemNumber FROM OorP LEFT JOIN dbo_FS_BillOfMaterial ON (OorP.itemkey = dbo_FS_BillOfMaterial.ParentItemKey AND dbo_FS_BillOfMaterial.ComponentItemNumber Like 'S_*' AND dbo_FS_BillOfMaterial.ComponentType='T');

Il result set è quello desiderato?

>Grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

Sembra di si.. ma purtroppo i dati non sono accessibili. La finestra di errore è modale e quindi non riesco a scorrere il risultato della query, appena la chiudo si chiude anche quella coi risultati. E poi non funziona con le tabelle linkate che contengono tutti i dati.
Hai provato ad eseguire la query ArtStampi2 sul database che ti ho inviato? non ti dà errori?
Idee?

Grazie
Davide

lbenaglia Profilo | Guru

>Sembra di si.. ma purtroppo i dati non sono accessibili.
Che significa "i dati non sono accessibili"?

>La finestra di errore è modale e quindi non riesco a scorrere il risultato
>della query, appena la chiudo si chiude anche quella coi risultati.
La query che ti ho passato non genera alcuna finestra di errore modale.

>E poi non funziona con le tabelle linkate che contengono tutti
>i dati.
Qua non posso aiutarti dato che non ho accesso al tuo sistema.

>Hai provato ad eseguire la query ArtStampi2 sul database che
>ti ho inviato? non ti dà errori?
Si, mi segnala l'errore "Espressione JOIN non supportata", ma non posso vedere il comando SQL che hai scritto.

>Grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

Ma se ti segnala l'errore non credo che tu possa scorrere i risultati nell finiestra sottostante. In ogni caso anche a te genera lo stesso problema.
Hai ragione, anche io non riesco ad accedere alla query SQL in design view... ma nel mdb originale si, eccola:

SELECT dbo_FS_Item.ItemNumber, dbo_FS_Item.ItemReference5, dbo_FS_Item.ItemDescription, dbo_FS_Item.ItemStatus, dbo_FS_Item.ItemClass1, dbo_FS_BillOfMaterial.ComponentItemNumber
FROM dbo_FS_Item LEFT JOIN dbo_FS_BillOfMaterial ON (dbo_FS_Item.itemkey = dbo_FS_BillOfMaterial.ParentItemKey
AND (dbo_FS_Item.ItemStatus='P' OR dbo_FS_Item.ItemStatus='O')
AND dbo_FS_BillOfMaterial.ComponentItemNumber Like 'S_*'
AND dbo_FS_BillOfMaterial.ComponentType='T');

Scusa e grazie,
Davide

lbenaglia Profilo | Guru

>SELECT dbo_FS_Item.ItemNumber, dbo_FS_Item.ItemReference5, dbo_FS_Item.ItemDescription,
>dbo_FS_Item.ItemStatus, dbo_FS_Item.ItemClass1, dbo_FS_BillOfMaterial.ComponentItemNumber
>FROM dbo_FS_Item LEFT JOIN dbo_FS_BillOfMaterial ON (dbo_FS_Item.itemkey
>= dbo_FS_BillOfMaterial.ParentItemKey
>AND (dbo_FS_Item.ItemStatus='P' OR dbo_FS_Item.ItemStatus='O')
>AND dbo_FS_BillOfMaterial.ComponentItemNumber Like 'S_*'
>AND dbo_FS_BillOfMaterial.ComponentType='T');

A me questa query funziona correttamente con l'mdb allegato al tuo post.

>Scusa e grazie,
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

A me continua a dare "espressione join non supportata" ...
Grazie,
Davide

lbenaglia Profilo | Guru

>A me continua a dare "espressione join non supportata" ...
Hai creato una NUOVA query nel db che hai allegato a questo thread incollando la tua ultima query?
Se non va potresti avere problemi con quella installazione di Access

>Grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

Davide.70 Profilo | Newbie

si... alla prima esecuzione nessun errore, poi "join non supportato" e non riesco nemmeno a riaprirla in designa view. Potrebbe essere dovuto al fatto che se la chiudi Access toglie le parentesi ed effettivamente la ON diventa ambigua? Grazie,
Davide

lbenaglia Profilo | Guru

>si... alla prima esecuzione nessun errore, poi "join non supportato"
>e non riesco nemmeno a riaprirla in designa view.
Io l'ho salvata e rieseguendola n volte non ho alcun errore.

>Potrebbe essere dovuto al fatto che se la chiudi Access toglie le parentesi ed
>effettivamente la ON diventa ambigua?
Potrebbe, ma non capisco perché a te la query viene modificata dopo la prima esecuzione.

>Grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5