SQL中的乘法聚合运算符

时间:2011-03-24 07:47:02

标签: sql sql-server oracle

在SQL中有聚合运算符,如AVG,SUM,COUNT。为什么它没有乘法运算符? “MUL”或其他什么。

我想知道,Oracle,MSSQL,MySQL是否存在?如果没有,是否会出现这种行为?

7 个答案:

答案 0 :(得分:40)

通过MUL,你的意思是逐步增加值吗?

即使有100行一些小尺寸(比如10s),你的MUL(列)也会溢出任何数据类型!由于错误/滥用的概率很高,而且使用范围非常有限,因此不需要是SQL标准。正如其他人已经表明的那样,有数学方法可以解决这个问题,就像使用标准(和常用)方法在SQL中进行棘手的计算有很多方法一样。

示例数据:

Column
1
2
4
8

COUNT : 4 items (1 for each non-null)
SUM   : 1 + 2 + 4 + 8 = 15
AVG   : 3.75 (SUM/COUNT)
MUL   : 1 x 2 x 4 x 8 ? ( =64 )

为了完整性,Oracle,MSSQL,MySQL核心实现*

Oracle : EXP(SUM(LN(column)))   or  POWER(N,SUM(LOG(column, N)))
MSSQL  : EXP(SUM(LOG(column)))  or  POWER(N,SUM(LOG(column)/LOG(N)))
MySQL  : EXP(SUM(LOG(column)))  or  POW(N,SUM(LOG(N,column)))
  • 在SQL Server中使用EXP / LOG时要小心,请注意返回类型http://msdn.microsoft.com/en-us/library/ms187592.aspx
  • POWER形式允许更大的数字(使用大于欧拉数的基数),并且在结果变得太大而无法使用POWER将其转回的情况下,您只能返回对数值并计算实际数字以外的数字。 SQL查询

<小时/> * LOG(0)和LOG(-ve)未定义。下面仅显示如何在SQL Server中处理此问题。使用相同的概念

可以找到其他SQL风格的等价物

create table MUL(data int)
insert MUL select 1 yourColumn union all
           select 2 union all
           select 4 union all
           select 8 union all
           select -2 union all
           select 0

select CASE WHEN MIN(abs(data)) = 0 then 0 ELSE
       EXP(SUM(Log(abs(nullif(data,0))))) -- the base mathematics
     * round(0.5-count(nullif(sign(sign(data)+0.5),1))%2,0) -- pairs up negatives
       END
from MUL

成分:

  • 取数据的abs(),如果min为0,则乘以其他任何东西是徒劳的,结果为0
  • 当数据为0时,NULLIF将其转换为null。 abs(),log()都返回null,导致它被sum()
  • 排除
  • 如果数据不是0,abs允许我们使用LOG方法将负数加倍 - 我们将跟踪其他地方的否定性
  • 制定最终标志
    • sign(data)返回1 for >00 for 0-1 for <0
    • 我们再添加0.5并再次取符号(),所以我们现在将0和1都归为1,并将-1归为-1。
    • 再次使用NULLIF从COUNT()中删除1,因为我们只需要计算负数。
    • % 2对负数的count()返回
    • - &GT;如果有一个奇数的负数,则为1
    • - &GT;如果存在偶数个负数,则为0
    • 更多数学技巧:我们取1或0关0.5,以便上面变为
    • - &GT; (0.5-1=-0.5 =&gt;舍入到 -1 ),如果有一个奇数的负数
    • - &GT; (0.5-0= 0.5 =&gt;轮到 1 )如果有偶数个负数
    • 我们将此最终1 / -1与实际结果的SUM-PRODUCT值进行多次比较

答案 1 :(得分:23)

不,但你可以使用数学:)

如果yourColumn总是大于零:

select EXP(SUM(LOG(yourColumn))) As ColumnProduct from yourTable

答案 2 :(得分:6)

我看到Oracle的答案仍然缺失,所以这里是:

SQL> with yourTable as
  2  ( select 1 yourColumn from dual union all
  3    select 2 from dual union all
  4    select 4 from dual union all
  5    select 8 from dual
  6  )
  7  select EXP(SUM(LN(yourColumn))) As ColumnProduct from yourTable
  8  /

COLUMNPRODUCT
-------------
           64

1 row selected.

的问候,
罗布。

答案 3 :(得分:1)

使用PostgreSQL,您可以创建自己的聚合函数,请参阅http://www.postgresql.org/docs/8.2/interactive/sql-createaggregate.html

要在MySQL上创建聚合函数,您需要构建.so(linux)或.dll(windows)文件。此处显示了一个示例:http://www.codeproject.com/KB/database/mygroupconcat.aspx

我不确定mssql和oracle,但我敢打赌他们也可以选择创建自定义聚合。

答案 4 :(得分:1)

随着数字的增加,你会很快打破任何数据类型。

使用LOG / EXP 棘手,因为数字&lt; = 0在使用LOG时会失败。我在this question中编写了一个处理此

的解决方案

答案 5 :(得分:0)

在MS SQL中使用CTE:

CREATE TABLE Foo(Id int, Val int)
INSERT INTO Foo VALUES(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)

;WITH cte AS 
(
    SELECT Id, Val AS Multiply, row_number() over (order by Id) as rn
    FROM Foo
    WHERE Id=1
    UNION ALL
    SELECT ff.Id, cte.multiply*ff.Val as multiply, ff.rn FROM
    (SELECT f.Id, f.Val, (row_number() over (order by f.Id)) as rn
    FROM Foo f) ff
        INNER JOIN cte
        ON ff.rn -1= cte.rn
)
SELECT * FROM cte

答案 6 :(得分:-2)

不确定Oracle或sql-server,但在MySQL中你可以像往常一样使用*

mysql> select count(id), count(id)*10 from tablename;
+-----------+--------------+
| count(id) | count(id)*10 |
+-----------+--------------+
|       961 |         9610 |
+-----------+--------------+
1 row in set (0.00 sec)