Evitare duplicati in una query di raggruppamento

di il
6 risposte

Evitare duplicati in una query di raggruppamento

Ciao a tutti.

Ho un problema con una query di raggruppamento.

Devo gestire delle carte rifornimento carburante facendone la contabilità mensile.

Ho completato tutto il calcolo contabile, ma nella stesura della documentazione richiesta sto avendo un problema su un riepilogo (il problema dell’oggetto).

Lavoro (per il problema in questione) su 2 tabelle: tblCedole e tblCedoleDett (in relazione uno-a-molti)

tblCedole: registro i dati generali delle carte rifornimento (progressivo, valore (50€), prezzo di acquisto carburante (cioè €/lt), etc)

tblCedoleDett: ogni volta che viene usata una tessera, registro qui i dati dell’uso (data, prezzo alla pompa, prezzo di acquisto carburante (quello della tabella precedente, lo riporto anche qui per comodità durante la contabilità), etc etc)

Ovviamente, quando si comprano le tessere, ad ogni tessera corrisponderà una quantità “amministrativa” di carburante (viene comprato ad un tot a litro), che al momento del rifornimento del mezzo (quindi quantità “reale”) può essere inferiore (nel caso il prezzo alla pompa sia maggiore) o superiore (se il prezzo alla pompa sia inferiore)

Su uno dei documenti contabili, ho bisogno di riepilogare le tessere utilizzate in base alla quantità “amministrativa”.

Il problema dell’uso delle tessere è che:

-          La tessera viene usata per intero

-          La tessera viene usata parzialmente, in 2 o più volte.

-          Può capitare di usare tessere comprate in tempi diversi (quindi €/lt “amministrativo” diversi)

Di conseguenza, nella tabella tblCedoleDett mi posso ritrovare (riduco l’esempio ai soli campi che mi interessano ora):

DATA

IDCarburante

IDCedola

SPESA

PrezzoAcquisto

1

1

1

50

1.710

3

1

2

30

1.710

4

1

2

20

1.710

6

1

3

20

1.820

7

1

3

20

1.820

NOTA: PrezzoAcquisto mi riferisco al prezzo/litro al momento di acquisto della tessera, non al prezzo alla pompa.

NOTA2: per IDCarburante uso 1 per Benzina e 2 per Gasolio

La query che sto provando è:

SELECT [IDCarburante], [PrezzoAcquisto], SUM(Spesa) as TotSpesa, Count([IDCedola]) AS TotaleCedole
FROM tblCedoleDett
WHERE [IDCarburante]= 1 AND DatePart('yyyy',[DataUso])=2025 And DatePart('m',[DataUso])=10
GROUP BY [IDCarburante],[PrezzoAcquisto]
ORDER BY [PrezzoAcquisto]

Nel caso dell’esempio di sopra:

1)      A parità di PrezzoAcquisto (quindi se PrezzoAcquisto fosse lo stesso per tutti i record), mi ritroverei che il campo TotaleCedole varrebbe 5

2)      Nel caso della tabella (cioè PrezzoAcquisto diversi), mi ritroverei con 2 TotaleCedole: 3 e 2

Cioè ottengo (nel caso della tabella di sopra - caso 2):

1

1.710

100

3

1

1.820

40

2

 Quando invece vorrei ottenere:

1

1.710

100

2

1

1.820

40

1

Notare che l’ultima tessera non è stata usata per il suo importo totale (motivo per il quale ho bisogno di quel campo SUM)

All’atto pratico, quello che devo riportare è qualcosa del genere:

-          mese di Ottobre: nr. X tessere da € 50 al prezzo di € 1.710 per Y litri e importo totale Z

   nr. X tessere da € 50 al prezzo di € 1.820 per Y litri e importo totale Z

 In definitiva quello che vorrei ottenere è un raggruppamento ma senza conteggiare i duplicati

Spero di essere stato chiaro nel descrivere la cosa.

Grazie

Andrea

6 Risposte

  • Re: Evitare duplicati in una query di raggruppamento

    Devi creare una query (a) che somma i totali spese e raggruppa per tessere oltre a filtrare per date

    Una query (b) che ricava il count della query (a)

    SELECT //query(a)
     IDCarburante,
     PrezzoAcquisto,
     IDCedola,
     SUM(Spesa) AS TotSpesaCedola
    FROM 
     tblCedoleDett
    WHERE 
     IDCarburante = 1
     AND DatePart('yyyy', DataUso) = 2025
     AND DatePart('m', DataUso) = 10
    GROUP BY 
     IDCarburante, 
     PrezzoAcquisto, 
     IDCedola;
    SELECT //(query b)
     A.IDCarburante,
     A.PrezzoAcquisto,
     SUM(A.TotSpesaCedola) AS TotSpesa,
     COUNT(*) AS TotaleCedole
    FROM 
         (query a) As A
    WHERE 
       A.TotSpesaCedola > 0 
    GROUP BY 
       A.IDCarburante, A.PrezzoAcquisto
    ORDER BY A.PrezzoAcquisto;
  • Re: Evitare duplicati in una query di raggruppamento

    Grazie per il supporto.

    Ho provato a seguire il tuo suggerimento, ma continuo a ricevere errore ("paramenti insufficienti previsto 2").

    Ho creato e salvato 2 query (qryVerbali1 e qryVerbali2) con questi enunciati:

    qryVerbali1:

    SELECT tblCedoleDett.IDCarburante, tblCedoleDett.PrezzoAcquisto, tblCedoleDett.IDCedola, Sum(tblCedoleDett.CaricoAmm) AS TotaleLitri, Sum(tblCedoleDett.Spesa) AS TotaleSpesa
    FROM tblCedoleDett
    WHERE (((DatePart('yyyy',[DataUso]))=Maschere!frmContabilita!txtIDAnno) And ((DatePart('m',[DataUso]))=Maschere!frmContabilita!txtIDMese))
    GROUP BY tblCedoleDett.IDCarburante, tblCedoleDett.PrezzoAcquisto, tblCedoleDett.IDCedola
    ORDER BY tblCedoleDett.IDCarburante;

    e qryVerbali2

    SELECT qryVerbali1.[IDCarburante], Sum(qryVerbali1.[TotaleLitri]) AS TotLitri, qryVerbali1.[PrezzoAcquisto], Sum(qryVerbali1.[TotaleSpesa]) AS TotSpesa, Count(qryVerbali1.[IDCedola]) AS TotaleCedole
    FROM qryVerbali1
    GROUP BY qryVerbali1.[IDCarburante], qryVerbali1.[PrezzoAcquisto]
    ORDER BY qryVerbali1.[PrezzoAcquisto];

    dove le uniche differenze rispetto al tuo suggerimento sono l'aggiunta del campo Somma TotLitri.

    Se lancio entrambe le query (ma anche solo qryVerbali2) ottengo i dati corretti che mi servono.

    Se però (limitatamente a qryVerbali2) provo a lavorarci in VBA (devo estrapolare i dati da inserire in in word), quando accedo al recordset ottengo l'errore "Parametri insufficienti, previsto 2".

    Questo sia che io scriva nell 'editor la query come:

    Set Rst = CurrentDb.OpenRecordset("SELECT A.IDCarburante, Sum(A.TotaleLitri) AS TotLitri, A.PrezzoAcquisto, Sum(A.TotaleSpesa) AS TotSpesa, Count(A.IDCedola) AS TotaleCedole" & _
    " FROM qryVerbali1 AS A" & _
    " WHERE A.IDCarburante= " & I & _
    " GROUP BY A.IDCarburante,A.PrezzoAcquisto" & _
    " ORDER BY A.PrezzoAcquisto", dbOpenSnapshot)

    (dove la I la prendo da un ciclo FOR...NEXT), sia che la scriva come:

    Set Rst = CurrentDb.OpenRecordset("qryVerbali2", dbOpenSnapshot)

    L'unica differenza che io vedo tra le due è che nella seconda ho omesso la clausola WHERE (e di conseguenza ho eliminato il ciclo FOR....NEXT), con l'intenzione poi di valutare i dati con un IF (se !IDCarburante =1 fai una cosa, se =2 fai un'altra cosa)

    Ora, se per la prima forma potrei capire un errore di parametro mancante visto che c'è una clausola WHERE (ma l'errore non c'è perchè se prima visualizzo il predicato nella finestra immediata, la condizione WHERE presenta correttamente =1), nella seconda, avendo eliminato la clausola WHERE non capisco che parametri manchino, visto che riprende i soli campi già filtrati dall qryVerbali1, senza alcun parametro da inserire

  • Re: Evitare duplicati in una query di raggruppamento

    Semplifico i campi (poi li sostituisci con i tuoi) e tolgo la data per brevità.

    CREATE TABLE SPESECARBURANTE (
      Id INTEGER PRIMARY KEY,
      IDCARBURANTE INTEGER NOT NULL,
      IDCEDOLA INTEGER NOT NULL,
      SPESA INTEGER NOT NULL,
      PREZZOUNITARIO INTEGER NOT NULL
    );
    
    -- insert
    INSERT INTO SPESECARBURANTE VALUES (1, 1, 1, 50, 1710);
    INSERT INTO SPESECARBURANTE VALUES (3, 1, 2, 30, 1710);
    INSERT INTO SPESECARBURANTE VALUES (4, 1, 2, 20, 1710);
    INSERT INTO SPESECARBURANTE VALUES (6, 1, 3, 20, 1820);
    INSERT INTO SPESECARBURANTE VALUES (7, 1, 3, 20, 1820);
    
    -- fetch 
    SELECT * FROM SPESECARBURANTE; // questa mi serve per verificare che i dati coincidono con la tua
    SELECT 
     A.IDCARBURANTE,
     A.PREZZOUNITARIO,
     SUM(A.TotSpesaCedola) AS TotSpesa,
     COUNT(*) AS TotaleCedole
    FROM 
      (SELECT 
       IDCARBURANTE,
       PREZZOUNITARIO,
       IDCEDOLA,
       SUM(SPESA) AS TotSpesaCedola
     FROM 
       SPESECARBURANTE
     WHERE 
       IDCARBURANTE = 1
     GROUP BY 
       IDCARBURANTE, 
       PREZZOUNITARIO, 
       IDCEDOLA) As A
         
    WHERE 
       A.TotSpesaCedola > 0 
    GROUP BY 
       A.IDCARBURANTE, A.PREZZOUNITARIO
    ORDER BY A.PREZZOUNITARIO;

    ottieni 

    questa è la tabella di partenza
    +----+--------------+----------+-------+----------------+
    | Id | IDCARBURANTE | IDCEDOLA | SPESA | PREZZOUNITARIO |
    +----+--------------+----------+-------+----------------+
    |  1 |            1 |        1 |    50 |           1710 |
    |  3 |            1 |        2 |    30 |           1710 |
    |  4 |            1 |        2 |    20 |           1710 |
    |  6 |            1 |        3 |    20 |           1820 |
    |  7 |            1 |        3 |    20 |           1820 |
    +----+--------------+----------+-------+----------------+
    
    questa la query select di select...
    +--------------+----------------+----------+--------------+
    | IDCARBURANTE | PREZZOUNITARIO | TotSpesa | TotaleCedole |
    +--------------+----------------+----------+--------------+
    |            1 |           1710 |      100 |            2 |
    |            1 |           1820 |       40 |            1 |
    +--------------+----------------+----------+--------------+
  • Re: Evitare duplicati in una query di raggruppamento

    Ho risolto !

    Grazie mille per il supporto e la pazienza

    Andrea

  • Re: Evitare duplicati in una query di raggruppamento

    01/12/2025 - Jocman ha scritto:

    Ho risolto !

    Grazie mille per il supporto e la pazienza

    Andrea

    Spero ti abbia capito che la seconda sql da errore perché va inserita all'interno dell'altra. Singolarmente una funziona l'altra no.

    Praticamente, ogni select ti restituisce una tabella. Tu stai facendo una query su questa tabella di risposta ( che hai chiamato as A). Ovvio che da sola non funziona perché manca la tabella (A) da manipolare.

    Ti ho messo campi diversi per farti ragionare.

    29/11/2025 - sihsandrea ha scritto:

    SELECT //(query b) A.IDCarburante, A.PrezzoAcquisto, SUM(A.TotSpesaCedola) AS TotSpesa, COUNT(*) AS TotaleCedole FROM (query a) As...

    La query tra parentesi, che devi includere con le parentesi, è la prima query alla quale fai una ulteriore query.

    Se hai fatto caso sono tutte precedute da a.

    SELECT 

     A.IDCARBURANTE,

     A.PREZZOUNITARIO,

     SUM(A.TotSpesaCedola) AS TotSpesa,

     COUNT(*) AS TotaleCedole

    Ecc....

    Al posto di A potevi mettere 'querysorgente'

    Diventano query sorgente.IDCARBURANTE ECC...

  • Re: Evitare duplicati in una query di raggruppamento

    Come sempren non smetto di imparare qualcosa di nuovo

    Grazie ancora

    Andrea

Devi accedere o registrarti per scrivere nel forum
6 risposte