none
Righe duplicate in query con UNION. Come risolvo? RRS feed

  • Domanda

  • Ciao.
    Ho questa query:

    ' Prima parte
    CustomSQL = CustomSQL & "SELECT Articoli.Id, Articoli.Codice, Articoli.Nome, Articoli.PrezzoVenditaLordo, SUM(MovimentiMagazzino.Quantita * MovimentiMagazzino.Molt) AS Giacenza" & vbCrLf
    CustomSQL = CustomSQL & "FROM           Articoli, MovimentiMagazzino" & vbCrLf
    CustomSQL = CustomSQL & "WHERE          Articoli.Id = MovimentiMagazzino.IdArticolo" & vbCrLf
    CustomSQL = CustomSQL & "GROUP BY       Articoli.Id, Articoli.Codice, Articoli.Nome, Articoli.PrezzoVenditaLordo" & vbCrLf
    
    CustomSQL = CustomSQL & "UNION" & vbCrLf
    
    ' Seconda parte
    CustomSQL = CustomSQL & "SELECT         Articoli.Id, Articoli.Codice, Articoli.Nome, Articoli.PrezzoVenditaLordo, 0 AS Giacenza" & vbCrLf
    CustomSQL = CustomSQL & "FROM           Articoli, MovimentiMagazzino" & vbCrLf
    CustomSQL = CustomSQL & "WHERE          Articoli.Id <> MovimentiMagazzino.IdArticolo" & vbCrLf
    CustomSQL = CustomSQL & "GROUP BY       Articoli.Id, Articoli.Codice, Articoli.Nome, Articoli.PrezzoVenditaLordo" & vbCrLf
    
    CustomSQL = CustomSQL & "ORDER BY       Articoli.Nome" & vbCrLf
    

    La prima parte di query mi visualizza SOLO gli articoli movimentati (cioè il cui Id è usato nella tabella MovimentiMagazzino).
    La seconda parte mi visualizza tutti gli articoli (sia movimentati che non movimentati).
    Io vorrei che in questa seconda parte di query apparissero solo gli articoli NON movimentati.
    Come posso risolvere?

    Grazie.



    • Modificato pascalman martedì 10 gennaio 2012 14:26
    martedì 10 gennaio 2012 14:14

Risposte

  • Ciao,

    questa estrazione la vedrei diversamente: ci sono vari metodi per quello che devi fare, una delle più lineari è la seguente:

    SELECT
        art.Id, art.Codice, art.Nome, art.PrezzoVenditaLordo, COALESCE(mag.Giacenza, 0) AS Giacenza
    FROM Articoli AS art
    LEFT JOIN 
    (
        SELECT mov.IdArticolo, SUM(mov.Quantita * mov.Molt) AS Giacenza
        FROM MovimentiMagazzino AS mov
        GROUP BY mov.IdArticolo
    ) AS mag ON art.Id = mag.IdArticolo
    ORDER BY art.Nome

    In pratica vedila così: recuperi tutti gli articoli, e a fianco ci scrivi l'eventuale giacenza di magazzino se c'è, altrimenti zero.

    Può andare?

    Ciao!


    Francesco Milano // .NET & SQL Server Consultant // blog // twitter
    • Contrassegnato come risposta pascalman martedì 10 gennaio 2012 19:33
    martedì 10 gennaio 2012 15:34
  • Ciao, Francesco.

    Grazie per la risposta.
    Tuttavia sia in Articoli che in MovimentiMagazzino non ho un campo Giacenza ma essa viene calcolata "al volo" ecco perche la mia query.

    Il tuo metodo mi piace ma devo capire bene sta storia del campo Giacenze



    OK, vediamo se riesco a spiegarti l'estrazione: parti dal concetto che tu gli articoli li hai, e la tabella Articoli rappresenta il tuo insieme di tutti gli articoli. Poi hai una tabella MovimentiMagazzino, che rappresenta un insieme di movimenti di articoli; potrebbero non essere tutti gli articoli della tabella Articoli, in quanto alcuni Articoli potrebbero non essere movimentati.

    A questo punto prendi la tabella MovimentiMagazzino e la raggruppi, in modo da avere una tabella risultante composta da IdArticolo e Giacenza (quest'ultima calcolata con la tua formula della tua prima union, cioè Quantita * Molt). Ottieni quindi una tabella (che ho chaiamato mag) che contiene tutti gli articoli movimentati con la loro giacenza calcolata. Questo passaggio che ti ho descritto è fatto nella FROM, più precisamente all'interno della LEFT JOIN. La LEFT JOIN tra "articoli" e "mag" indica al motore di recuperare tutti i record di Articoli e quelli di mag per cui trova una corrispondenza di IdArticolo. Se la corrispondenza non c'è, viene passato un NULL per i campi di mag che estraiamo nella SELECT finale (in questo caso, solo Giacenza).

    In ultima istanza, la COALESCE indica quale valore restituire se viene trovato un valore NULL nella giacenza, nel nostro caso quindi 0.

    Sono riuscito ad essere più chiaro? Se no chiedi pure :)


    Francesco Milano // .NET & SQL Server Consultant // blog // twitter
    • Contrassegnato come risposta pascalman martedì 10 gennaio 2012 19:33
    martedì 10 gennaio 2012 16:56

Tutte le risposte

  • Ciao,

    questa estrazione la vedrei diversamente: ci sono vari metodi per quello che devi fare, una delle più lineari è la seguente:

    SELECT
        art.Id, art.Codice, art.Nome, art.PrezzoVenditaLordo, COALESCE(mag.Giacenza, 0) AS Giacenza
    FROM Articoli AS art
    LEFT JOIN 
    (
        SELECT mov.IdArticolo, SUM(mov.Quantita * mov.Molt) AS Giacenza
        FROM MovimentiMagazzino AS mov
        GROUP BY mov.IdArticolo
    ) AS mag ON art.Id = mag.IdArticolo
    ORDER BY art.Nome

    In pratica vedila così: recuperi tutti gli articoli, e a fianco ci scrivi l'eventuale giacenza di magazzino se c'è, altrimenti zero.

    Può andare?

    Ciao!


    Francesco Milano // .NET & SQL Server Consultant // blog // twitter
    • Contrassegnato come risposta pascalman martedì 10 gennaio 2012 19:33
    martedì 10 gennaio 2012 15:34
  • Ciao, Francesco.

    Grazie per la risposta.
    Tuttavia sia in Articoli che in MovimentiMagazzino non ho un campo Giacenza ma essa viene calcolata "al volo" ecco perche la mia query.

    Il tuo metodo mi piace ma devo capire bene sta storia del campo Giacenze

    martedì 10 gennaio 2012 15:46
  • Ciao, Francesco.

    Grazie per la risposta.
    Tuttavia sia in Articoli che in MovimentiMagazzino non ho un campo Giacenza ma essa viene calcolata "al volo" ecco perche la mia query.

    Il tuo metodo mi piace ma devo capire bene sta storia del campo Giacenze



    OK, vediamo se riesco a spiegarti l'estrazione: parti dal concetto che tu gli articoli li hai, e la tabella Articoli rappresenta il tuo insieme di tutti gli articoli. Poi hai una tabella MovimentiMagazzino, che rappresenta un insieme di movimenti di articoli; potrebbero non essere tutti gli articoli della tabella Articoli, in quanto alcuni Articoli potrebbero non essere movimentati.

    A questo punto prendi la tabella MovimentiMagazzino e la raggruppi, in modo da avere una tabella risultante composta da IdArticolo e Giacenza (quest'ultima calcolata con la tua formula della tua prima union, cioè Quantita * Molt). Ottieni quindi una tabella (che ho chaiamato mag) che contiene tutti gli articoli movimentati con la loro giacenza calcolata. Questo passaggio che ti ho descritto è fatto nella FROM, più precisamente all'interno della LEFT JOIN. La LEFT JOIN tra "articoli" e "mag" indica al motore di recuperare tutti i record di Articoli e quelli di mag per cui trova una corrispondenza di IdArticolo. Se la corrispondenza non c'è, viene passato un NULL per i campi di mag che estraiamo nella SELECT finale (in questo caso, solo Giacenza).

    In ultima istanza, la COALESCE indica quale valore restituire se viene trovato un valore NULL nella giacenza, nel nostro caso quindi 0.

    Sono riuscito ad essere più chiaro? Se no chiedi pure :)


    Francesco Milano // .NET & SQL Server Consultant // blog // twitter
    • Contrassegnato come risposta pascalman martedì 10 gennaio 2012 19:33
    martedì 10 gennaio 2012 16:56
  • Perfetto, funziona alla grande.

    Ti ringrazio infinitamente.

    martedì 10 gennaio 2012 19:33
  • Perfetto, funziona alla grande.

    Ti ringrazio infinitamente.


    Niente, figurati, è un piacere :)
    Francesco Milano // .NET & SQL Server Consultant // blog // twitter
    martedì 10 gennaio 2012 19:50