J'essaie d'obtenir le produit de toutes les lignes pour une colonne spécifique dans une requête groupée. La plupart des exemples que j'ai trouvés m'orientent vers la combinaison de exp
, sum
et log
exp(sum(log([Column A])))
Le problème que j'ai est que la colonne contient des zéros pour les valeurs et donc j'obtiens cette erreur lorsque les zéros sont passés à la fonction log
:
Une opération à virgule flottante non valide s'est produite.
Je pensais pouvoir contourner cela en utilisant une expression case
, mais cela ne fonctionne tout simplement pas comme je le pense, car il semble évaluer tous les cas ...
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
Étant donné l'ensemble de résultats suivant:
Id Name Value
_________________________________
1 a 1
2 a 2
3 b 0
4 b 1
Je m'attendrais à obtenir les lignes suivantes:
Name Product
_____________
a 2
b 0
Donc en résumé ... Comment multipliez-vous des lignes dans une colonne qui peuvent contenir des nombres négatifs ou nuls?
La magie de NULLIF semble faire l'affaire pour le cas de test dans votre question. Puisque vous avez utilisé un exemple différent de celui de votre SQL Fiddle, je ne sais pas si c'est ce que vous voulez là aussi.
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;
Retour:
Name Product
a 2
b 0
Si vous avez besoin d'une solution plus générale qui gère les nombres négatifs et autres cas Edge, consultez par exemple Le produit agrégé dans T-SQL contre le CLR par Scott Burkow. Une construction T-SQL de cet article est:
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)
Quant à savoir pourquoi votre expression CASE
d'origine n'a pas fonctionné comme prévu, à partir de la documentation de CASE (Transact-SQL) (emphase ajoutée):
Vous ne devez dépendre que de l'ordre d'évaluation des conditions WHEN pour les expressions scalaires (y compris les sous-requêtes non corrélées qui renvoient des scalaires), pas pour les expressions agrégées .