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

Je cherche quelque chose comme SELECT PRODUCT(table.price) FROM table GROUP BY table.sale similaire à la façon dont fonctionne SUM .

Ai-je manqué quelque chose sur la documentation, ou n’y a-t-il vraiment aucune fonction PRODUCT ?

Si oui, pourquoi pas?

Note: J’ai cherché la fonction dans postgres, mysql et mssql et je n’ai trouvé aucune fonction, donc je suppose que tout SQL ne le supporte pas.

Il n’y a pas de fonction de set de produits dans le standard SQL. Cela semblerait être un bon candidat (contrairement à, par exemple, une fonction d’ensemble CONCATENATE : ce n’est pas un bon choix pour SQL, par exemple le type de données résultant impliquerait des CONCATENATE et poserait problème en ce qui concerne la première forme normale).

Les normes SQL visent à consolider les fonctionnalités des produits SQL vers 1990 et à fournir un «leadership éclairé» en matière de développement futur. En bref, ils documentent ce que fait SQL et ce que SQL doit faire. L’absence de fonction de produit suggère qu’en 1990 aucun fournisseur ne méritait d’être inclus et qu’il n’y avait aucun intérêt académique à l’introduire dans la norme.

Bien sûr, les fournisseurs ont toujours cherché à append leurs propres fonctionnalités, généralement ces dernières années, plutôt que des extensions de normes plutôt que des extensions tangentes. Je ne me souviens pas avoir vu une fonction d’ensemble de produits (ou même une demande) dans l’un des produits SQL que j’ai utilisés.

Dans tous les cas, le travail est assez simple à l’aide log fonctions scalaires log et exp (et de la logique pour gérer les négatifs) avec la fonction d’ensemble SUM ; voir la réponse de @gbn pour un exemple de code. Je n’ai jamais eu besoin de le faire dans une application métier.

En conclusion, ma meilleure hypothèse est qu’il n’ya pas de demande de la part des utilisateurs SQL pour une fonction de set PRODUCT ; de plus, quiconque ayant un intérêt académique trouverait probablement la solution de rechange acceptable (c.-à-d. qu’il ne valoriserait pas le sucre syntaxique qu’une fonction d’ensemble de produits fournirait).

Sans intérêt, il existe effectivement une demande dans SQL Server Land pour les nouvelles fonctions de jeu, mais pour celles de la variété de fonctions de fenêtre (et de SQL standard également). Pour plus de détails, y compris sur la manière de participer à la demande, consultez le blog d’Itzik Ben-Gan .

Pour MSSQL, vous pouvez l’utiliser. Il peut être adopté pour d’autres plates-formes: ce ne sont que des mathématiques et des agrégats sur les 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 

Tiré de ma réponse ici: SQL Server Query - Multiplication par groupes

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

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

Vous pouvez effectuer une fonction d’agrégation de produits, mais vous devez faire les calculs 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/

Il y a une astuce dans T-SQL (je ne suis pas sûr que ce soit ANSI) qui permet de concaténer des valeurs de chaîne d’un ensemble de lignes en une seule variable. Il semble que cela fonctionne aussi bien pour se multiplier:

 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.

Je pense que c’est parce qu’aucun système de numérotation ne peut accueillir de nombreux produits. Comme les bases de données sont conçues pour un grand nombre d’enregistrements, un produit de 1 000 numéros serait extrêmement massif et, en cas de nombres à virgule flottante, l’erreur propagée serait énorme.

Notez également que l’utilisation de log peut être une solution dangereuse. Bien que logistiquement (a * b) = log (a) * log (b), il peut ne pas être dans les ordinateurs car nous ne traitons pas avec des nombres réels. Si vous calculez 2 ^ (log (a) + log (b)) au lieu de * b, vous pouvez obtenir des résultats inattendus. Par exemple:

SELECT 9999999999 * 99999999974482, EXP (LOG (9999999999) + LOG (99999999974482))

dans Sql Server renvoie

999999999644820000025518, 9.99999999644812E + 23

Donc, ce que je veux dire, c’est que lorsque vous essayez de faire le produit, faites-le soigneusement et que le test est lourd.

Une façon de résoudre ce problème (si vous travaillez dans un langage de script) consiste à utiliser la fonction group_concat. Par exemple, SELECT group_concat(table.price) FROM table GROUP BY table.sale

Cela retournera une chaîne avec tous les prix pour la même valeur de vente, séparés par une virgule. Ensuite, avec un parsingur, vous pouvez obtenir chaque prix et faire une multiplication. (Dans php, vous pouvez même utiliser la fonction array_reduce, en fait, dans le manuel php.net, vous obtenez un exemple approprié).

À votre santé