56 votes

Pourquoi n'y a-t-il pas de fonction d'agrégation PRODUCT dans SQL ?

Je recherche quelque chose comme SELECT PRODUCT(table.price) FROM table GROUP BY table.sale similaire au fonctionnement de SUM .

Ai-je raté quelque chose sur la documentation, ou n'y a-t-il vraiment pas de fonction PRODUCT ?

Si oui, pourquoi pas ?

Remarque: j'ai cherché la fonction dans postgres, mysql et mssql et n'en ai trouvé aucune, j'ai donc supposé que tout sql ne la supportait pas.

58voto

gbn Points 197263

Pour MSSQL, vous pouvez l'utiliser. Il peut être adopté pour d'autres plateformes : c'est juste des maths et des agrégats sur des logarithmes.

 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

Extrait de ma réponse ici : requête SQL Server - multiplication par groupe

34voto

Lord Peter Points 1395

Je ne sais pas pourquoi il n'y en a pas, mais (faites plus attention aux nombres négatifs), vous pouvez utiliser des journaux et des exposants pour faire :-

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

8voto

Steve Fenton Points 55265

Vous pouvez effectuer une fonction d'agrégat de produit, mais vous devez faire le calcul vous-même, comme ceci...

 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

Source : http://productfunctionsql.codeplex.com/

6voto

David Airapetyan Points 667

Il existe une astuce intéressante dans T-SQL (je ne sais pas si c'est ANSI) qui permet de concaténer des valeurs de chaîne à partir d'un ensemble de lignes en une seule variable. Il semble que cela fonctionne également pour la multiplication :

 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

Cela peut potentiellement être plus stable numériquement que la solution log/exp.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X