Как умножить строки для столбца, который содержит отрицательные и нулевые значения?

10

Я пытаюсь получить продукт всех строк для определенного столбца в группе по запросу. Большинство примеров, которые я нашел, указывают мне на объединение exp, sumи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

Итак, в заключение ... Как вы умножаете строки в столбце, который может содержать отрицательные или нулевые числа?

bluetoft
источник

Ответы:

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

Если вам нужно более общее решение, которое обрабатывает отрицательные числа и другие крайние случаи, см., Например, Сводка продукта в 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 для скалярных выражений (включая некоррелированные подзапросы, которые возвращают скаляры), а не для агрегированных выражений .

Эрик Дарлинг
источник