2010-10-12 15 views
40

Sto cercando qualcosa come SELECT PRODUCT(table.price) FROM table GROUP BY table.sale simile a come funziona SUM.Perché non esiste una funzione di aggregazione del PRODOTTO in SQL?

Ho perso qualcosa sulla documentazione, o c'è davvero alcuna funzione PRODUCT?

Se sì, perché no?

Nota: ho guardato per la funzione in Postgres, MySQL e MSSQL e ha trovato nessuno così ho assunto tutti sql non lo supporta.

+1

Immagino che sia molto più raro voler calcolare il prodotto su una serie di numeri rispetto a una somma. Anche nel tuo esempio, quanto spesso desideri calcolare il prodotto di un insieme di prezzi? –

+1

Qual è il valore del prodotto (table.price) che si suppone risponda? Leggendo la "funzione di aggregazione del prodotto", ho capito che è necessario restituire il prodotto di tutti i valori table.price trovati nel set di risultati: Row1.Price * Row2.Price * ... * RowN.Price. Ma per la vita di me, non riesco a capire cosa significhi "quel valore", quali informazioni dovrebbe trasmettere? Qual è l'applicazione pratica di questo, per i prezzi o qualsiasi altro tipo di valore? Per favore, illuminami. –

+4

per il mio caso non è in realtà per i prezzi, ma per ottenere un prodotto di rendimento (qty_out/qty_in). – lock

risposta

24

Non c'è alcuna funzione PRODUCT insieme nello standard SQL. Sembrerebbe essere un candidato degno, tuttavia (a differenza, per esempio, di una funzione set CONCATENATE: non è adatto per SQL, ad esempio il tipo di dati risultante coinvolgerebbe multivaleri e pone un problema per quanto riguarda la prima forma normale).

SQL standard mirano a consolidare la funzionalità attraverso i prodotti SQL circa 1990 e per fornire 'leadership di pensiero' per lo sviluppo futuro. In breve, documentano cosa fa SQL e cosa dovrebbe fare SQL. L'assenza della funzione set PRODUCT suggerisce che nel 1990 nessun venditore fosse degno di inclusione e non ci fosse stato alcun interesse accademico a introdurlo nello Standard.

Naturalmente, i venditori sempre hanno cercato di aggiungere la propria funzionalità, in questi giorni di solito come estensioni a standard piuttosto che tangentally. Non ricordo di aver visto una funzione set PRODUCT (o anche una richiesta per uno) in uno qualsiasi dei prodotti SQL che ho usato.

In ogni caso, il lavoro è abbastanza semplice utilizzando le funzioni scalari log e exp (e la logica per gestire i negativi) con la funzione set SUM; vedi la risposta di @ gbn per qualche codice di esempio. Non ho mai avuto bisogno di farlo in un'applicazione aziendale, però.

In conclusione, la mia ipotesi migliore è che non vi è alcuna richiesta da parte degli utenti finali SQL per una funzione set PRODUCT; inoltre, chiunque abbia un interesse accademico probabilmente troverà la soluzione accettabile (vale a dire non darebbe valore allo zucchero sintattico fornito da una funzione set PRODUCT).

Fuori di interesse, v'è infatti richiesta in SQL Server terreni per le nuove funzioni impostate ma per quelli della funzione finestra varietà (e SQL standard, anche). Per maggiori dettagli, incluso come essere coinvolti in ulteriori richieste di guida, vedere Itzik Ben-Gan's blog.

+2

+1 "Non esiste una funzione di set di prodotti nello standard SQL, ma sembrerebbe essere un candidato degno, anche se" - così sarebbe una funzione di media geometrica. –

+0

Purtroppo questa risposta è assolutamente sbagliata. exp (sum (log (column))) funziona alla grande con numeri positivi o vedere le risposte migliori qui sotto. – Chris

+0

Mark, geo mean è questo: exp (avg (log (x))) – Chris

7

È possibile eseguire una funzione di aggregazione del prodotto, ma si deve fare i conti da soli, come questo ...

SELECT 
    Exp(Sum(IIf(Abs([Num])=0,0,Log(Abs([Num])))))*IIf(Min(Abs([Num]))=0,0,1)*(1-2*(Sum(IIf([Num]>=0,0,1)) Mod 2)) AS P 
FROM 
    Table1 

Fonte: http://productfunctionsql.codeplex.com/

14

Non so perché non c'è uno, ma (fare più attenzione su numeri negativi) è possibile utilizzare i registri e gli esponenti di fare: -

select exp (sum (ln (table.price))) from table ... 
+2

Aggiungi round() se stai calcolando il prodotto dei valori di una colonna intera. A volte viene restituito il valore .9999 ... invece di un intero int. – inam101

45

per MSSQL è possibile utilizzare questo. Può essere adottato per altre piattaforme: è solo matematica e aggregati sui logaritmi.

SELECT 
    GrpID, 
    CASE 
     WHEN MinVal = 0 THEN 0 
     WHEN Neg % 2 = 1 THEN -1 * EXP(ABSMult) 
     ELSE EXP(ABSMult) 
    END 
FROM 
    (
    SELECT 
     GrpID, 
     --log of +ve row values 
     SUM(LOG(ABS(NULLIF(Value, 0)))) AS ABSMult, 
     --count of -ve values. Even = +ve result. 
     SUM(SIGN(CASE WHEN Value < 0 THEN 1 ELSE 0 END)) AS Neg, 
     --anything * zero = zero 
     MIN(ABS(Value)) AS MinVal 
    FROM 
     Mytable 
    GROUP BY 
     GrpID 
    ) foo 

preso dalla mia risposta qui: SQL Server Query - groupwise multiplication

+4

"è solo matematica e aggregati sui logaritmi" :) 'log (a * b * c ... * n) = log (a) + log (b) + log (c) ... + log (n) ' – onedaywhen

+3

seriamente @gbn, tu sei l'uomo. – FistOfFury

3

Penso che sia perché nessun sistema di numerazione è in grado di ospitare molti prodotti.Dato che i database sono progettati per un numero elevato di record, un prodotto di 1000 numeri sarebbe enorme e, in caso di numeri in virgola mobile, l'errore propagato sarebbe enorme.

Si noti inoltre che l'utilizzo del registro può essere una soluzione pericolosa. Anche se matematicamente log (a * b) = log (a) * log (b), potrebbe non essere nei computer poiché non si tratta di numeri reali. Se si calcola 2^(log (a) + log (b)) invece di a * b, si potrebbero ottenere risultati imprevisti. Per esempio:

SELEZIONARE 9999999999 * 99.999.999,974482 millions, EXP (LOG (9999999999) + LOG (99999999974482))

in SQL Server restituisce

999999999644820000025518, 9.99999999644812E + 23

Quindi il mio punto è quando stai provando a fare il prodotto, fallo con attenzione e prova molto.

1

Un modo per risolvere questo problema (se si sta lavorando in un linguaggio di scripting) è utilizzare la funzione group_concat. Ad esempio, SELECT group_concat(table.price) FROM table GROUP BY table.sale

Ciò restituirà una stringa con tutti i prezzi per lo stesso valore di vendita, separati da una virgola. Quindi con un parser è possibile ottenere ogni prezzo e fare una moltiplicazione. (In php si può anche usare la funzione array_reduce, infatti nello php.net manual si ottiene un esempio adatto).

Acclamazioni

5

C'è un trucco in T-SQL (non so se si tratta di ANSI) che consente di concatenare i valori di stringa da una serie di righe in una variabile. Sembra che funziona per moltiplicare così:

declare @Floats as table (value float) 
insert into @Floats values (0.9) 
insert into @Floats values (0.9) 
insert into @Floats values (0.9) 

declare @multiplier float = null 

select 
    @multiplier = isnull(@multiplier, '1') * value 
from @Floats 

select @multiplier 

Ciò può potenzialmente essere più numericamente stabile rispetto alla soluzione di log/exp.

+0

Incredibile! Grazie! –

Problemi correlati