Newsgroup: it.comp.lang.visual-basic
Titolo: Query con INNER JOIN

Buongiorno a voi,
sono alle prese con una query access da vb6, dalla quale dovrei
estrarre dati in una modalità che non ho mai utilizzato.
Tabella Fabbrica e tabella Ingrosso, con campi comuni
Data -idcliente - Cliente - importo
 
Vorrei caricare in una griglia, i relativi saldi per ogni comparto 
raggruppati per cliente (al momento...) ed ho impostato la query così:
 
rsSaldi.Source = "Select Ingrosso.Cliente AS iCLI,Fabbrica.Cliente As 
FCli,Sum(Ingrosso.Importo) as Itot,SUM(Fabbrica.Importo) AS Ftot " _
     & "from Ingrosso LEFT JOIN FABBRICA ON ingrosso.idcliente = 
Fabbrica.idcliente Group BY Ingrosso.Cliente,Fabbrica.Cliente"
 
Tuttavia vedo che se un cliente non è presente nella tabella fabbrica,
non viene restituito, a causa dell' ON ingrosso.idcliente = 
fabbrica.idcliente"
Ovviamente se lo imposto su RIGHT ho il caso inverso.
Io vorrei invece avere le somme di importo per tutti i clienti presenti 
in ingrosso ed in fabbrica, e avere 0 se nell'uno o nell'altro
comparto, il nome non è presente.
Potreste aiutarmi a risolvere? Sto procedendo per gradi, in quanto
dovrei poi ricavare la data dell'acquisto più recente e quella 
dell'acquisto più vecchio, ma quella è un'altra storia...
 
Grazie a tutti
 
 


Effettuando una ricerca in rete, ho appreso che alle istruzioni
left join e right join, oltre che a outer, esiste un'ulteriore
istruzione, FULL JOIN oppure FULL OUTER JOIN, ma entrambe mi danno
un errore nell'apertura del recordset (Metodo open del recorset non 
riuscito)
Intanto, l'esempio riportato, riguarda un db access...
 
Aiuto?
 

Il 28/03/2012 14:04, Marco ha scritto:
< Mi autotaglio>
 
Dopo una intensa sollecitazione del mio unico neurone,
sono riuscito ad impostare una query che rimpiazzasse il
full join non supportato, creando una query che strutturata in tre parti
mi restituisce i risultati che volevo.
Il fatto è che non capisco il motivo per cui la somma dei campi importo 
nelle due tabelle unite, non corrisponde a quella reale, ma raddoppia
rispetto al numero di incroci delle tabelle. E' giusta solo in presenza 
di un record nell'una o nell'altra tabella.
Potreste per favore dargli uno sguardo e vedere cosa sbaglio?
Spero in un vostro aiuto
Grazie
 
rsSaldi.Source = "Select Ingrosso.IdCliente AS C1,Ingrosso.Cliente AS 
C2,Fabbrica.IDCliente AS C3,Fabbrica.Cliente AS C4,Sum(Ingrosso.Importo) 
AS T1,Sum(Fabbrica.Importo) AS T2 " _
  & "From ingrosso INNER  join fabbrica on 
ingrosso.idcliente=fabbrica.idcliente GROUP BY 
INGROSSO.IDCLIENTE,FABBRICA.IDCLIENTE,ingrosso.cliente,fabbrica.cliente " _
  & "UNION ALL " _
  & "Select Ingrosso.IdCliente AS C1,Ingrosso.Cliente AS 
C2,Fabbrica.IDCliente AS C3,Fabbrica.Cliente AS C4,Sum(Ingrosso.Importo) 
AS T1,Sum(Fabbrica.Importo) AS T2 " _
  & "From ingrosso LEFT join fabbrica on 
ingrosso.idcliente=fabbrica.idcliente WHERE (((Fabbrica.IDCliente) Is 
Null)) GROUP BY 
INGROSSO.IDCLIENTE,FABBRICA.IDCLIENTE,ingrosso.cliente,fabbrica.cliente " _
  & "UNION ALL " _
  & "Select Ingrosso.IdCliente AS C1,Ingrosso.Cliente AS 
C2,Fabbrica.IDCliente AS C3,Fabbrica.Cliente AS C4,Sum(Ingrosso.Importo) 
AS T1,Sum(Fabbrica.Importo) AS T2 " _
  & "From ingrosso RIGHT join fabbrica on 
ingrosso.idcliente=fabbrica.idcliente WHERE (((Ingrosso.IDCliente) Is 
Null)) GROUP BY 
INGROSSO.IDCLIENTE,FABBRICA.IDCLIENTE,ingrosso.cliente,fabbrica.cliente"
 

 un errore nell'apertura del recordset (Metodo open del recorset non riuscito)
 
Volendo escludere un errore di sintassi (perchè immagino che la query 
tu l'abbia prima provata in una finestrella Sql), non vorrei che tu 
aprissi il recordset in qualche modalità scrivibile. Non so come Access 
possa gestire un full outer join in scrittura.
 
Riproverei con la virgola.
 
Alberto
 
 


Grazie per la risposta Alberto,
nei miei post successivi, ho chiarito di aver risolto questo problema.
Piuttosto che usare il full outer join, ho fatto la union di più 
query,descrivendola di seguito.
Il problema in realtà, sta nel fatto che per come è scritta questa 
query, il risultato della somma dei campi inreressati, si moltiplica in 
maniera progressiva presenza di più record, nel senso che se cliente 1 
ha 2 record per 100 euro in una tabella e 3 record da 50 nella seconda,
i totali raddoppiano. Non ne so uscire.
Intanto provo anche il tuo suggerimento circa full join, ma quest'altro 
problema rimane.
Potresti per favore dare un'occhiata al post successivo?
Grazie
Marco
 

Nel suo scritto precedente, Marco ha sostenuto :

Per carità...
 
Non mi metto a guardare una query copiaincollata da vb6.
Le query mica si provano così, si copiaincollano dal debug di vb6 e si 
testano nelle finestrelle sql del database, così in 5' si trovano i 
problemi.
Poi, se non si risolve, si posta la query, non il mostro con le 
concatenazioni.
Comunque, al di là dell'aspetto leggibilità, se indichi ALL ammetti i 
duplicati della Union (a prescindere che non so cosa tu stia 
'unionando'), quindi se uno ha problemi di duplicazione, io inizierei 
sempre dal rimuovere la clausola ALL.
 
Anche se, pur non avendo letto ciò che vuoi ottenere (io replicavo solo 
sul discorso del full outer join, non nel merito dei dati), mi sembra 
estremamente arzigogolato sostituire un full outer join con una 
Union...
 
Alberto
 
 


...Infatti, l'unico dato certo, è che sono un pò somaro, ma ci ho 
sbattuto la testa contro per due giorni per riuscire ad impostare la 
query che mi restituisse il risultato sperato.
La finalità è quella di ottenere i totali per cliente da due tabelle, 
nelle quali il cliente potrebbe non essere presente in entrambe 
contemporaneamente. Quindi, avendo id,nome ed importo in entrambe le 
tabelle, ho ritenuto che il full outer join fosse la soluzione più 
adatta.Per ritrovarmi invece con il messaggio metodo open dell'oggetto 
recordset non riuscito. Allora ho creato quel mostro che ho copincollato 
prima. Senza la union non saprei come risolvere. Questo è un altro dato 
certo...
 

Scriveva Marco venerdì, 30/03/2012:

Guarda, non entro nel merito dello specifico.
Scrivo a braccio un esempio, poi devi adattarlo tu.
Abbiamo tre tabelle, l'anagrafica dei clienti, i movimenti di tipo A e 
i movimenti di tipo B (che ipotizziamo memorizzati in due tabelle 
distinte, anche se non è così che andrebbe fatto).
Tu vuoi il totale dei movimenti A e il totale dei movimenti B, per ogni 
cliente.
SELECT ANAG.CLIENTE
, TOT_A = SUM(COALESCE(A.QUANTITA),0)
, TOT_B = SUM(COALESCE(B.QUANTITA),0)
FROM ANAGRAFICA AS ANAG
LEFT OUTER JOIN MOVIMENTI_A AS A
 ON 
ANAG.ID
 = 
A.ID
 
LEFT OUTER JOIN MOVIMENTI_B AS B
 ON 
ANAG.ID
 = 
B.ID
 
GROUP BY ANAG.CLIENTE
 
Ma ipotizziamo che per qualche motivo del tutto a me incomprensibile, 
non si voglia utilizzare l'anagrafica, e quindi si vogliano usare 
solamente le due tabelle dei movimenti:
SELECT
CLIENTE = COALESCE(A.CLIENTE, B.CLIENTE)
, TOT_A = COALESCE(A.QUANTITA,0)
, TOT_B = COALESCE(B.QUANTITA,0)
FROM
    (SELECT CLIENTE, QUANTITA = SUM(QUANTITA)
     FROM MOVIMENTI_A
     GROUP BY CLIENTE) AS A
FULL OUTER JOIN
    (SELECT CLIENTE, QUANTITA = SUM(QUANTITA)
     FROM MOVIMENTI_B
     GROUP BY CLIENTE) AS B
ON A.CLIENTE = B.CLIENTE
 
Più in dettaglio non saprei cosa dirti, questa qui sopra è una sintassi 
T-Sql, vedi tu come adattarla in Access.
Inoltre ignora per il momento l'apertura del recordset, quello lo fai 
alla fine, per adesso devi ovviamente sviluppare solamente la parte SQL 
nell'apposita finestrellina in Access.
 
Alberto
 
 

 , TOT_B = SUM(COALESCE(B.QUANTITA),0)
 
Parentesi nel punto sbagliato:
 , TOT_A = SUM(COALESCE(A.QUANTITA,0))
 , TOT_B = SUM(COALESCE(B.QUANTITA,0))
 
 
Alberto
 
 

Sembra che Albe V° abbia detto :

Beh, poi è sbagliata concettualmente, sorry.
Va fatta in modo simile all'altro caso, anche usando la tabella di 
anagrafica come prima tabella a sinistra...
 
Alberto
 
 


 
 
Grazie di cuore Albe, l'ho appena letta.
Intanto provo a vedere come funziona e come eventualmente riadattarla, 
anche se ad un primo sguardo, la logica di esecuzione, renderebbe quello 
che a me serve.
Adesso provo.
 
Marco


Dunque...l'ho riadattata per access, cambiando qualcosa tipo il 
coalesce, ma continua a dirmi errore di sintassi (operatore mancante)
dopo la riga del left outer join.
Spezzata in due parti, la prima funziona. L'ho riscritta così
 
rs.Source = "SELECT TAB_A.CLIENTE AS CLI, 
SUM(iif(isnull(TAB_A.Importo),0)) AS TOT_A, 
SUM(iif(isnull(TAB_B.Importo),0)) AS TOT_B
FROM TAB_A " _
LEFT OUTER JOIN TAB_B ON TAB_A.IDCliente=TAB_B.IdCliente LEFT OUTER JOIN 
TAB_B ON TAB_B.IdCliente=TAB_A.IdCliente"
 
Volevo oltretutto provarla su access 2000 ma non trovo una casella come 
tu dicevi per scrivere la query, la dovrei creare in visualizzazione 
struttura o altro...
 
 
 
 
 
 

 TAB_B ON TAB_B.IdCliente=TAB_A.IdCliente"
 
Come già detto, non mi metto neanche a guardare la roba scritta in vb6.
Le query si scrivono in SQL.
Comunque quel iif(isnull è brutto brutto, secondo me non c'entra niente 
con la sintassi Access (ma, appunto, finchè non si ha la praticità di 
commentare e decommentare al volo nella finestrella, non ci si salta 
fuori).
 
 
Alberto
 
 


Intanto mi fido si!, i tuoi post come quelli di qualche altro sono un 
libro dal quale apprendere, quanto al metodo, ne prendo atto, si impara 
dagli errori e si fa tesoro dell'esperienza degli altri, quindi ti 
ringrazio anche per avermi detto questo, che trovo ancor più importante 
di tutto il resto.
Venendo al codice, visto che coalesce non è una sintassi valida per 
access, ho cercato l'equivalente, non immaginavo che l'iif isnull fosse 
tanto orrendo!
Grazie comunque davvero per la tua pazienza. Probabilmente non 
risolverò, ma avrò certamente imparato ancora.
 
Marco