T-SQL中的累计乘法

时间:2015-09-24 10:49:19

标签: sql sql-server tsql sql-server-2008-r2

GTS表

CCP months   QUART   YEARS  GTS
----  ------  -----    ----- ---
CCP1    1       1   2015    5
CCP1    2       1   2015    6
CCP1    3       1   2015    7
CCP1    4       2   2015    4
CCP1    5       2   2015    2
CCP1    6       2   2015    2
CCP1    7       3   2015    3
CCP1    8       3   2015    2
CCP1    9       3   2015    1
CCP1    10      4   2015    2
CCP1    11      4   2015    3
CCP1    12      4   2015    4

基准表

CCP BASELINE   YEARS    QUART
----  --------   -----  -----
CCP1    5       2015    1

预期结果

CCP months  QUART    YEARS  GTS   result
----  ------  -----    ----- ---   ------

CCP1    1       1   2015    5     25   -- 5 * 5 (here 5 is the baseline)
CCP1    2       1   2015    6     30   -- 6 * 5 (here 5 is the baseline)
CCP1    3       1   2015    7     35   -- 7 * 5 (here 5 is the baseline)
CCP1    4       2   2015    4     360  -- 90 * 4(25+30+35 = 90 is the basline)
CCP1    5       2   2015    2     180  -- 90 * 2(25+30+35 = 90 is the basline)
CCP1    6       2   2015    2     180  -- 90 * 2(25+30+35 = 90 is the basline)
...
next quarter baseline will be (720)

SQLFIDDLE

Explantion

基线表具有每个CCP的单一基线值。

基准值应适用于每个CCP的第一季度,并且对于下一季度,上一季度的总和值将是basleine。

是的我可以使用While循环或光标来做到这一点,但我正在寻找更好的方法到目前为止我尝试过这样的事情。但是没有说出我在这里失踪的东西。

查询

;WITH RECURSIVE_CTE
     AS (SELECT B.CCP,
                G.months,
                g.years,
                g.quart,
                Cast(( B.BASELINE + GTS ) AS NUMERIC(38, 15))AS BASE,
                Sum(Cast(( B.BASELINE + GTS ) AS NUMERIC(38, 15)))OVER(PARTITION BY b.CCP) AS Q_SUM
         FROM   BASELINE B
                INNER JOIN GTS G
                        ON B.CCP = G.CCP
                           AND b.QUART = g.QUART
                           AND b.YEARS = g.YEARS
         UNION ALL
         SELECT G.CCP,
                G.months,
                g.years,
                g.quart,
                Cast(( Q_SUM + GTS ) AS NUMERIC(38, 15)),
                Sum(Cast(( Q_SUM + GTS ) AS NUMERIC(38, 15)))OVER(PARTITION BY g.CCP, g.years, g.quart) AS Q_SUM
         FROM   RECURSIVE_CTE C
                INNER JOIN GTS G
                        ON C.CCP = G.CCP
                           AND G.YEARS = C.YEARS and g.QUART = c.quart + 1)
SELECT *
FROM   RECURSIVE_CTE

注意:我在Sql Server 2008

中寻找建议

2 个答案:

答案 0 :(得分:2)

我认为如果你在递归锚中添加一个行号,那么将cte中的连接限制为每季度只有3行中的一行,就可以达到你想要的结果:

publish_pages

这会产生:

WITH CTE AS
(   SELECT  b.CCP,
            Baseline = CAST(b.Baseline AS DECIMAL(15,2)),
            b.Years,
            b.Quart,
            g.Months,
            g.GTS,
            Result = CAST(b.Baseline * g.GTS AS DECIMAL(15,2)),
            NextBaseline = SUM(CAST(b.Baseline * g.GTS AS DECIMAL(15, 2))) OVER(PARTITION BY g.CCP, g.years, g.quart),
            RowNumber = ROW_NUMBER() OVER(PARTITION BY g.CCP, g.years, g.quart ORDER BY g.Months)
    FROM    #GTS AS g
            INNER JOIN #Base AS b
                ON B.CCP = g.CCP
               AND b.QUART = g.QUART
               AND b.YEARS = g.YEARS
    UNION ALL
    SELECT  b.CCP,
            CAST(b.NextBaseline AS DECIMAL(15, 2)),
            b.Years,
            b.Quart + 1,
            g.Months,
            g.GTS,
            Result = CAST(b.NextBaseline * g.GTS AS DECIMAL(15,2)),
            NextBaseline = SUM(CAST(b.NextBaseline * g.GTS AS DECIMAL(15, 2))) OVER(PARTITION BY g.CCP, g.years, g.quart),
            RowNumber = ROW_NUMBER() OVER(PARTITION BY g.CCP, g.years, g.quart ORDER BY g.Months)
    FROM    #GTS AS g
            INNER JOIN CTE AS b
                ON B.CCP = g.CCP
               AND b.Quart + 1 = g.QUART
               AND b.YEARS = g.YEARS
               AND b.RowNumber = 1
)
SELECT  CCP, Months, Quart, Years, GTS, Result, Baseline
FROM    CTE;

示例数据

CCP     Months  Quart   Years   GTS     Result      Baseline
-------------------------------------------------------------
CCP1    1       1       2015    5       25.00       5.00
CCP1    2       1       2015    6       30.00       5.00
CCP1    3       1       2015    7       35.00       5.00
CCP1    4       2       2015    4       360.00      90.00
CCP1    5       2       2015    2       180.00      90.00
CCP1    6       2       2015    2       180.00      90.00
CCP1    7       3       2015    3       2160.00     720.00
CCP1    8       3       2015    2       1440.00     720.00
CCP1    9       3       2015    1       720.00      720.00
CCP1    10      4       2015    2       8640.00     4320.00
CCP1    11      4       2015    3       12960.00    4320.00
CCP1    12      4       2015    4       17280.00    4320.00

答案 1 :(得分:1)

也许还有其他更好的方法,但这应该适合你:

样本日期

CREATE TABLE #gts
(
    CCP NVARCHAR(20),
    months INT,   
    QUART INT,  
    YEARS NVARCHAR(20),  
    GTS INT
)

CREATE TABLE #BASELINE
(
    CCP NVARCHAR(20),
    baseline INT,     
    YEARS NVARCHAR(20),
    QUART INT

)

INSERT INTO #gts VALUES
('CCP1',    1 ,      1,  '2015',    5),
('CCP1',    2 ,      1,  '2015',    6),
('CCP1',    3 ,      1,  '2015',    7),
('CCP1',    4 ,      2,  '2015',    4),
('CCP1',    5 ,      2,  '2015',    2),
('CCP1',    6 ,      2,  '2015',    2),
('CCP1',    7 ,      3,  '2015',    3),
('CCP1',    8 ,      3,  '2015',    2),
('CCP1',    9 ,      3,  '2015',    1),
('CCP1',    10,      4,  '2015',    2),
('CCP1',    11,      4,  '2015',    3),
('CCP1',    12,      4,  '2015',    4)

INSERT INTO #baseline VALUES ('CCP1', 5, '2015', 1)

<强> QUERY

SELECT          
    B.CCP,
    G.months,
    g.years,
    g.quart,
    Cast(( B.BASELINE * GTS ) AS NUMERIC(38, 15))AS BASE,
    Sum(Cast(( B.BASELINE * GTS ) AS NUMERIC(38, 15)))OVER(PARTITION BY b.CCP) AS Q_SUM
INTO #temp
FROM   #BASELINE B
    INNER JOIN #GTS G
            ON B.CCP = G.CCP
                AND b.QUART = g.QUART
                AND b.YEARS = g.YEARS        
DECLARE @i INT
SET @i = 1
WHILE @i <= 3
BEGIN
INSERT INTO #temp 
SELECT DISTINCT 
    G.CCP,
    G.months,
    g.years,
    g.quart,                
    Cast(( Q_SUM * GTS ) AS NUMERIC(38, 15)),
    Sum(Cast(( BASE * GTS ) AS NUMERIC(38, 15)))OVER(PARTITION BY g.CCP, g.years, g.quart) AS Q_SUM

FROM   #temp C
    INNER JOIN #GTS G
            ON C.CCP = G.CCP
                AND G.YEARS = C.YEARS 
                AND g.QUART = c.quart + 1
SET @i = @i +1
END


SELECT DISTINCT CCP,
                months,
                years,
                quart,
                BASE
INTO #result
FROM #temp

SELECT * 
FROM #result

drop table #baseline
drop table #gts
drop table #temp
drop table #result

<强>输出

CCP months  years   quart   BASE
CCP1    1   2015    1       25.000000000000000
CCP1    2   2015    1       30.000000000000000
CCP1    3   2015    1       35.000000000000000
CCP1    4   2015    2       360.000000000000000
CCP1    5   2015    2       180.000000000000000
CCP1    6   2015    2       180.000000000000000
CCP1    7   2015    3       2160.000000000000000
CCP1    8   2015    3       1440.000000000000000
CCP1    9   2015    3       720.000000000000000
CCP1    10  2015    4       8640.000000000000000
CCP1    11  2015    4       12960.000000000000000
CCP1    12  2015    4       17280.000000000000000