为什么SQL中没有PRODUCT聚合函数?

我正在寻找像SELECT PRODUCT(table.price) FROM table GROUP BY table.sale类似于SUM工作方式。

我在文档上遗漏了什么,还是真的没有PRODUCTfunction?

如果是这样,为什么不呢?

注:我在postgres,mysql和mssql中查找函数,发现没有,所以我认为所有的SQL不支持它。

SQL标准中没有PRODUCT设置function。 这似乎是一个值得的候选人,虽然(不像一个CONCATENATE设置function:它不是一个很好的适合于SQL,例如最终的数据types会涉及多值,并提出一个问题,关于第一范式)。

SQL标准旨在于1990年左右整合SQL产品的function,并为未来的发展提供“思想领导”。 简而言之,他们logging了SQL的作用和SQL应该做的事情。 没有PRODUCTfunction表明,在1990年没有供应商值得纳入,而且没有将其引入标准的学术兴趣。

当然,供应商总是试图增加自己的function,这些通常是对标准的扩展,而不是相反。 我不记得在我使用过的任何SQL产品中看到了PRODUCT设置function(甚至不需要)。

在任何情况下,使用SUM设置函数使用logexp标量函数(以及用于处理底片的逻辑)的解决方法相当简单; 有关示例代码,请参阅@ gbn的答案。 不过,我从来没有需要在商业应用程序中这样做。

总而言之,我最好的猜测是,SQLterminal用户对于一个PRODUCT设置函数没有需求; 进一步说,任何有学术兴趣的人都可能会find可以接受的解决方法(即不会重视PRODUCT集函数提供的语法糖)。

出于兴趣,SQL Server Land确实需要新的集合函数,但对于窗口函数变种(以及标准SQL)也是如此。 有关更多详情,包括如何参与进一步的驾驶需求,请参阅Itzik Ben-Gan的博客 。

对于MSSQL你可以使用这个。 它可以用于其他平台:它只是math和对数的总和。

 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 

从我的答案在这里采取: SQL Server查询 – 分组乘法

我不知道为什么没有一个,但(对负数更加谨慎),你可以使用日志和指数来做:

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

你可以执行一个产品聚合函数,但你必须自己做math,就像这样…

 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 

资料来源: http : //productfunctionsql.codeplex.com/

在T-SQL(不确定是否是ANSI)中有一个巧妙的技巧,允许将一组行中的string值连接成一个variables。 它看起来也可以用于乘法运算:

 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 

这可能比log / exp解决scheme更具数值稳定性。

我认为这是因为没有编号系统能够容纳许多产品。 由于数据库是为大量的logging而devise的,所以1000个数字的乘积将是超级大的,在浮点数的情况下,传播的错误将是巨大的。

另请注意,使用日志可能是一个危险的解决scheme。 尽pipe在math上logging(a * b)= log(a)* log(b),它可能不在计算机中,因为我们没有处理实数。 如果计算2 ^(log(a)+ log(b))而不是a * b,则可能会得到意想不到的结果。 例如:

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

在Sql Server中返回

999999999644820000025518,9.99999999644812E + 23

所以我的观点是,当你试图做产品时要小心谨慎,testing是很重要的。

处理这个问题的一种方法(如果你使用的是脚本语言)是使用group_concat函数。 例如, SELECT group_concat(table.price) FROM table GROUP BY table.sale

这将返回一个string与所有价格相同的销售价值,用逗号分隔。 然后用parsing器,你可以得到每个价格,并做一个乘法。 (在PHP中,你甚至可以使用array_reduce函数,实际上在php.net手册中你会得到一个合适的例子)。

干杯