如何为包含负值和零值的列乘行?


10

我试图获取按查询分组的特定列的所有行的乘积。我发现的大多数示例都将我引向了expsum并且log

exp(sum(log([Column A])))

我遇到的问题是该列包含一些零值,因此当零传递给log函数时出现此错误:

发生无效的浮点运算。

我以为我可以通过使用case表达式来解决这个问题,但是那似乎并没有像我认为的那样起作用,因为它似乎可以评估所有情况。

select 
  Name,
  Product = case 
    when min([Value]) = 0 then 0 
    when min([Value]) <> 0 then exp(sum(log(I))) -- trying to get the product of all rows in this column
  end
 from ids
 group by Name

SqlFiddle

给定以下结果集:

Id  Name  Value
_________________________________
1   a     1
2   a     2
3   b     0
4   b     1

我希望得到以下行:

Name  Product
_____________
a     2
b     0

因此,总而言之...如何在一列中可以包含负值或零值的行相乘?

Answers:


13

NULLIF的魔力似乎可以解决问题中的测试用例。由于您使用的示例与SQL Fiddle中的示例不同,因此我也不知道您是否也想要那样。

CREATE TABLE dbo.Ids
(
    Id INT NOT NULL IDENTITY(1, 1),
    Value INT,
    Name NVARCHAR(3)
);
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'a', 1 );
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'a', 2 );
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'b', 0 );
INSERT INTO dbo.Ids ( Name, Value )
VALUES ( 'b', 1 );

SELECT   Name,
         CASE WHEN MIN(Value) = 0 THEN 0
              WHEN MIN(Value) > 0 THEN EXP(SUM(LOG(NULLIF(Value, 0)))) -- trying to get the product of all rows in this column
         END AS Product
FROM     Ids
GROUP BY Name;

返回值:

Name    Product
a       2
b       0

如果需要处理负数和其他极端情况的更通用的解决方案,请参见例如Scott Burkow撰写的《T-SQL中的产品汇总与CLR》。该文章中的一种T-SQL构造是:

EXP(SUM(LOG(NULLIF(ABS([Value]), 0))))
*
IIF(SUM(IIF([Value] = 0, 1, NULL)) > 0, 0, 1)
*
IIF(SUM(IIF([Value] < 0, 1, 0)) % 2 = 1, -1, 1)

关于您的原始CASE表达式为何无法按预期工作的原因,请参见CASE(Transact-SQL)的文档(添加了重点):

对于标量表达式(包括返回标量的非相关子查询),而不是聚合表达式,您应该仅取决于WHEN条件的评估顺序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.