Selezione di righe doppie con clausula IN

di il
11 risposte

Selezione di righe doppie con clausula IN

Buongiorno a tutti,

avrei bisogno di estrarre il totale prezzo di un elenco di articoli scelti, fino a qui nulla di difficile ovviamente.

Alla pagina PHP arriva un array con gli id_articolo selezionati, ora io volevo evitare di fare un ciclio e fare una select per elemento dell'array per estrarre il prezzo.

Avevo pensato a una cosa del tipo
SELECT SUM(prezzo) as totale FROM tab_articoli WHERE id_articolo IN (1,2,3...)
ma il problema è che l'array può avere più volte lo stesso articolo del tipo [2,3,3,4,5,8,8... ]

Come posso fare per creare una query unica ed estrarre il totale direttamente dal DB ?

Grazie!

11 Risposte

  • Re: Selezione di righe doppie con clausula IN

    Senza sapere nulla di più:
    
    SELECT SUM(prezzo) as totale
    FROM tab_articoli
    WHERE id_articolo IN (
       SELECT DISTINCT id_articolo
       FROM tab_articoli
       WHERE id_articolo IN (2, 3, 3, 4, 5, 8, 8...)
    )
    
  • Re: Selezione di righe doppie con clausula IN

    Grazie per la risposta ma non è corretta.

    la tua query è paragonabile a quella che ho scritto già io e che restituisce il totale per ogni ID nell'array ma ignora se sono doppi.

    Se per esempio i primi 3 articoli hanno questi prezzi

    1 -> 3,00
    2 -> 5,00
    3 -> 6,00

    e l'array degli articoli selezionati è [1,1,2,3,3] il totale dovrebbe essere 23,00 (3+3+5+6+6) mentre sia la mia query che la tua restituiscono 14,00
  • Re: Selezione di righe doppie con clausula IN

    Scusa, avevo capito che a te servisse esattamente il contrario (cioè, rimuovere i duplicati), cosa che la clausola IN dovrebbe effettivamente fare da sola.
    La sola cosa che mi viene in mente è usare una tabella temporanea, da popolare con i valori che ti servono. Una tabella con due campi:

    Tabella temp_articolo:
    id_tmp - Autoincrement
    id_articolo int

    Popoli prima la tabella in modo da avere tutti gli articoli, uno per riga (ciascuno con il proprio id_temp univoco)
    
    DELETE FROM temp_articolo;  -- Svuotiamo la tabella
    
    -- Riempiamo con i valori che ci servono
    INSERT INTO temp_articolo(id_articolo)
    VALUES(2),(2),(3),(4),(5),(5),...
    
    Quindi:
    
    SELECT SUM(A.prezzo) as totale
    FROM tab_articoli A INNER JOIN temp_articolo B ON (A.id_articolo = B.id_articolo)
    
  • Re: Selezione di righe doppie con clausula IN

    Grazie! Si mi sembra una buona soluzione, non avevo pensato ad una tabella temporanea.
  • Re: Selezione di righe doppie con clausula IN

    Eeeehhhhh?????
  • Re: Selezione di righe doppie con clausula IN

    +m2+ ha scritto:


    Eeeehhhhh?????
    non capisco, vuoi aggiungere una tua considerazione?
  • Re: Selezione di righe doppie con clausula IN

    Si, che francamente creare una tabella temporanea mi pare giusto un pochino esagerato.
    un pochino.
    alla pagina php arriva un array, cosa significa esattamente? Da dove arriva?
    PS esiste anche OR (che è vel non aut) , ma intanto vediamo da dove arriva
  • Re: Selezione di righe doppie con clausula IN

    Ok spiego meglio il flusso.

    In una pagina vengono scelti degli articoli da acquistare, non è comune che si scelga più volte lo stesso articolo ma in qualche caso può succedere e quindi questo genera il problema di cui sopra.

    Ogni volta che si sceglie un articolo nella tabella "carrello" della pagina stessa viene aggiunta una riga e contestualmente salvavo l'id_articolo in un array.
    Allo stesso tempo dovevo aggiornare il totale dell'ordine e quindi l'idea era quella di interrogare il DB con una chiamata $.post passando appunto l'array degli articoli scelti.
    Se gli id_articolo nell'array fossero tutti diversi una semplice query con la clausula IN ( array_passato ) mi restituiva il totale corretto, ma se nell'array ho valori doppi e MySql li ignora ( giustamente ).

    Ieri ho provato la gestione con la tabella temporanea ma lato pratico non si è rivelata ottimale ( viene creata e distrutta ad ogni aggiunta articolo ).

    Alla fine ho cambiato completamente approccio, creando una tabella normale in cui inserisco gli articoli ad ogni scelta con l'aggiunta di un valore che è id_conto che viene generato all'apertura della pagina.
    In modo posso poi filtrare gli articoli per la gestione futura, come per la generazione del totale che ora è semplice e per il salvataggio finale dell'ordine in quanto farò poi un insert sulla tabella ordini facendo un select sulla tabella articoli_temp filtrando appunto per id_conto.
  • Re: Selezione di righe doppie con clausula IN

    +m2+ ha scritto:


    Si, che francamente creare una tabella temporanea mi pare giusto un pochino esagerato.
    un pochino.
    alla pagina php arriva un array, cosa significa esattamente? Da dove arriva?
    PS esiste anche OR (che è vel non aut) , ma intanto vediamo da dove arriva
    Beh, avevo precisato nella mia prima risposta "Senza saperne nulla di più".
    Ad ogni modo sarei curioso di conoscere la soluzione mediante l'uso di una OR che non elimini i valori duplicati (mi pareva di ricordare che la clausola IN venisse "trasformata" sottobanco in una serie di OR).

    @Eranius: messa in questi termini la problematica è ben diversa... quello che ti serve è una tabella che rappresenti realmente un carrello in cui gli articoli possono essere inseriti anche "doppi".

    PS: se la temporanea si svuota ad ogni inserimento è perchè hai copiato il codice di esempio pari pari senza capirlo (e che c'era pure scritto nel commento che prima veniva svuotata per far posto ad una nuova serie di insert... è chiaro che se le insert le fai in momenti diversi non devi svuotare ad ogni inserimento... quindi la DELETE non va fatta ad ogni inserimento... e nemmeno ricrearla: va creata all'inizio e poi usata finchè non ne hai più bisogno. Mi sembrava piuttosto ovvio e banale)
  • Re: Selezione di righe doppie con clausula IN

    SpiritoLibero ha scritto:


    PS: se la temporanea si svuota ad ogni inserimento è perchè hai copiato il codice di esempio pari pari senza capirlo (e che c'era pure scritto nel commento che prima veniva svuotata per far posto ad una nuova serie di insert... è chiaro che se le insert le fai in momenti diversi non devi svuotare ad ogni inserimento... quindi la DELETE non va fatta ad ogni inserimento... e nemmeno ricrearla: va creata all'inizio e poi usata finchè non ne hai più bisogno. Mi sembrava piuttosto ovvio e banale)
    Forse mi sono espresso mail io, è ovvio che eventualmente avrei creato la tabella temp una volta solo all'apertura della pagina, ma il DELETE lo devo fare ogni volta se passo l'array intero degli articoli, altrimenti dovrei passare l'id_articolo singolo che va aggiunto o rimosso.

    Quindi trovando migliore l'idea di inserire il singolo articolo ho optato per la soluzione sopra descritta ovvero una tabella normale, tanto viene mantenuta pulita.
  • Re: Selezione di righe doppie con clausula IN

    Francamente sono sempre approcci diciamo così dilettanteschi.
    in una situazione del genere non si utilizzano array php, ma tabelle memory, fino a quando non viene confermato.
    in questo caso, con una singola transazione, si copia nella tabella finale in un colpo solo.
    questo fa sì che non si usa memoria php (ovviamente per sitarelli con 3 utenti si può fare qualsiasi cosa) e si è certi che in caso di blocco le righe verranno comunque scritte con il lock più piccolo possibile in scrittura.
    di nuovo se hai 3 utenti non succede nulla.
    se ne hai 30.000 non si possono tenere transazioni pendenti su larga scala
Devi accedere o registrarti per scrivere nel forum
11 risposte