Як помножити рядки для стовпця, який містить від’ємні та нульові значення?


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

Отже, підсумовуючи ... Як ви перемножуєте рядки в стовпчик, який може містити від’ємні чи нульові значення?

Відповіді:


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 Versus 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 для скалярних виразів (включаючи некорельовані підзапити, які повертають скаляри), а не для сукупних виразів .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.