Running Multiplication in T-SQL

后端 未结 6 1273
無奈伤痛
無奈伤痛 2021-02-03 13:16

GTS Table

CCP months   QUART   YEARS  GTS
----  ------  -----    ----- ---
CCP1    1       1   2015    5
CCP1    2       1   2015    6
CCP1    3       1   2015         


        
6条回答
  •  遇见更好的自我
    2021-02-03 14:08

    Following solution assumes there are always 3 rows per quarter (only the last quarter might be partial), single SELECT, no recursion :-)

    WITH sumQuart AS
     (
       SELECT *,
          CASE
            WHEN ROW_NUMBER() -- for the 1st month in a quarter
                 OVER (PARTITION BY CCP, Years, Quart
                       ORDER BY months) = 1
                      -- return the sum of all GTS of this quarter
            THEN SUM(GTS) OVER (PARTITION BY CCP, Years, Quart)
            ELSE NULL -- other months
          END AS sumGTS
       FROM gts
     )
    ,cte AS
     (
       SELECT 
          sq.*,
          COALESCE(b.Baseline, -- 1st quarter
                   -- product of all previous quarters
                   CASE
                     WHEN MIN(ABS(sumGTS)) -- any zeros?
                          OVER (PARTITION BY sq.CCP ORDER BY sq.Years, sq.Quart, sq.Months 
                                ROWS BETWEEN UNBOUNDED PRECEDING AND 3 PRECEDING) = 0 
                       THEN 0  
                     ELSE -- product
                          EXP(SUM(LOG(NULLIF(ABS(COALESCE(b.Baseline,1) * sumGTS),0)))
                              OVER (PARTITION BY sq.CCP ORDER BY sq.Years, sq.Quart, sq.Months 
                                    ROWS BETWEEN UNBOUNDED PRECEDING AND 3 PRECEDING)) -- product
                          -- odd number of negative values -> negative result
                        * CASE WHEN COUNT(CASE WHEN sumGTS < 0 THEN 1 END) 
                                    OVER (PARTITION BY sq.CCP ORDER BY sq.Years, sq.Quart, sq.Months 
                                          ROWS BETWEEN UNBOUNDED PRECEDING AND 3 PRECEDING) % 2 = 0 THEN 1 ELSE -1 END
                   END) AS newBaseline
       FROM sumQuart AS sq
       LEFT JOIN BASELINE AS b
              ON B.CCP = sq.CCP
              AND b.Quart = sq.Quart
              AND b.Years = sq.Years
     )
    SELECT 
       CCP, months, Quart, Years, GTS,
       round(newBaseline * GTS,2),
       round(newBaseline,2)
    FROM cte
    

    See Fiddle

    EDIT: Added logic to handle values <= 0 Fiddle

提交回复
热议问题