Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Agrégat de multiplication dans SQL Server

Je n'utiliserais pas la fonction scalaire pour ce type d'opération. Vous vous retrouvez avec des performances médiocres car l'optimiseur de requête doit l'exécuter row-by-row sans aucune optimisation. Plus d'informations :SQL Server Functions: The Basics .

Deuxième avec flottant/décimal et LOG/EXP vous obtiendrez des erreurs d'approximation.

Troisièmement pour transmettre des données à la fonction, vous pouvez utiliser XML comme :

CREATE FUNCTION dbo.udf_Mul(@value xml)
RETURNS FLOAT
AS
  BEGIN
      DECLARE @mul_value FLOAT;
      DECLARE @values AS TABLE ([value] float);

       INSERT INTO @values([value])
       SELECT [value] = t.c.value('(value)[1]', 'float')
      FROM @value.nodes('//row') AS t(c);


      SELECT @mul_value=CASE
               WHEN MinVal = 0 THEN 0
               WHEN Neg % 2 = 1 THEN -1 * Exp(ABSMult)
               ELSE Exp(ABSMult)
             END 
      FROM   (SELECT
             Sum(Log(Abs(NULLIF(Value, 0)))) AS ABSMult,
             Sum(Sign(CASE
                        WHEN Value < 0 THEN 1
                        ELSE 0
                      END))                  AS Neg,
             Min(Abs(Value))                 AS MinVal
              FROM   @values) foo

      RETURN @mul_value
  END 

et en l'appelant :

SELECT *
FROM Floats a
CROSS APPLY (SELECT dbo.udf_mul((SELECT [value]
                                 FROM Floats b
                                 WHERE a.id >= b.id
                                 FOR XML PATH, ROOT('root')))
             AS r) as cs(r);

SqlFiddleDemo

Sortie :

╔═════╦════════╦════════════════════╗
║ id  ║ value  ║         r          ║
╠═════╬════════╬════════════════════╣
║  1  ║     1  ║ 1                  ║
║  2  ║     3  ║ 3.0000000000000004 ║
║  3  ║     6  ║ 17.999999999999996 ║
║  4  ║     2  ║ 36                 ║
╚═════╩════════╩════════════════════╝