Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Query con INNER JOIN

26 views
Skip to first unread message

Marco

unread,
Mar 28, 2012, 7:22:39 AM3/28/12
to
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


Marco

unread,
Mar 28, 2012, 8:04:08 AM3/28/12
to
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?

Marco

unread,
Mar 30, 2012, 6:07:13 AM3/30/12
to
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"

Albe V°

unread,
Mar 30, 2012, 6:17:37 AM3/30/12
to
Marco ci ha detto :
Il full outer join equivale alla versione old-style del join, eseguito
mediante la semplice elencazione delle tabelle separate da virgola, e
con i criteri di join impostati nel where.
Sostanzialmente, avviene un prodotto cartesiano delle n tabelle, poi
nel where si filtrava solo la parte buona della matrice
multidimensionale.
Col full outer join c'è la comodità di avere tutto nel ON e quindi il
motore ottimizza molto meglio.
Nel tuo caso, se Access non lo supporta, basta usare la virgola e il
where.

> ma entrambe mi danno
> 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


Marco

unread,
Mar 30, 2012, 6:31:36 AM3/30/12
to
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

Albe V°

unread,
Mar 30, 2012, 6:49:58 AM3/30/12
to
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


Marco

unread,
Mar 30, 2012, 7:03:57 AM3/30/12
to
...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...

Albe V°

unread,
Mar 30, 2012, 8:53:03 AM3/30/12
to
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


Albe V°

unread,
Mar 30, 2012, 8:54:34 AM3/30/12
to
Albe V° ha pensato forte :
> , TOT_A = SUM(COALESCE(A.QUANTITA),0)
> , 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


Albe V°

unread,
Mar 30, 2012, 8:56:20 AM3/30/12
to
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


Marco

unread,
Mar 30, 2012, 9:23:23 AM3/30/12
to
Il 30/03/2012 14:56, Albe V° ha scritto:
> Sembra che Albe V° abbia detto :
>> (cut perchè non invia...)
>>
>> 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
>
> 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

Marco

unread,
Mar 30, 2012, 10:06:54 AM3/30/12
to
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...






Albe V°

unread,
Mar 30, 2012, 10:31:32 AM3/30/12
to
Marco scriveva il 30/03/2012 :
> 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.

Marco, sinceramente.
Se stai sviluppando per piacere o per studio, va bene tutto e
mettiamola in ridere.
Ma se sviluppi per lavoro, ti invito a valutare il metodo, ben prima
che le capacità o le competenze o l'esperienza.

Se ti dico che le query NON si sviluppano in vb6 ma in una finestrella
Sql, le possibilità sono solo due:
- ti fidi di me
- non ti fidi di me

Se, come auspico, ti fidi di me, occorre che tu lasci perdere il tuo
procedere a tentoni e inizi a strutturare un metodo.
E quindi ben prima di provare a far funzionare la query, devi trovare
la finestrella sql.
Adesso, sono anni che non uso Access (per mia fortuna), ma se ricordo
bene si poteva fare creando una qualunque query a caso, anche con solo
un campo, con quel coso QBE che offre Access, poi c'era un bottoncino
che consentiva di vedere la stessa roba 'trasformata' in SQL.
Quella roba era tranquillamente cancellabile e ci potevi scrivere
quello che volevi, quindi LI' si sviluppano le query.
E poi, ma solo poi, le si copiaincollano in vb6.


> 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"

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


Marco

unread,
Mar 30, 2012, 10:41:45 AM3/30/12
to
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
0 new messages