2015-09-10 152 views
0

我的數據按ID和checkdate分組,以便每個人對於每個checkDate都有一行,他們收到一張支票。我爲每個checkDate列出總額(YTDGross)和延期金額(YTD401K)。使用SQL Server 2012中的計算列進行計算

我想計算3個額外的列。

第一計算使用下式的匹配量(匹配度):

IIF(YTD401K<=.04*YTDGross,IIF(YTDGross<=265000,YTD401K-PriorYTD401kMatch, 
IIF((YTD401K-PriorYTD401kMatch)>(10600-PriorYTD401kMatch),10600-PriorYTD401kMatch,YTD401K-PriorYTD401kMatch)), 
IIF(YTDGross<=265000,(ROUND(.04*YTDGross,2)-PriorYTD401kMatch),10600-PriorYTD401kMatch)) AS Match 

的公式本身是不相干的不同之處在於它是指另一列也需要計算:PriorYTD401kMatch。而這一列依次是從第三列計算的 - 它是上一行的YTD401KMatch。

YTD401KMatch簡直是PriorYTD401kMatch +匹配

我看不出這是SQL Server 2012中爲每一個三個新列的可能是一個迂迴的方式彼此依賴。有人隨時向我展示燈光。

下面是最新的選擇,我堅持之前:

SELECT 
c.co, 
c.id, 
c.checkDate, 
yg.gross, 
yg.YTDGross, 
c.cont401k, 
SUM(c.cont401k) OVER (PARTITION BY c.id ORDER BY c.checkDate) AS YTD401K, 
c.match401K, 
SUM(c.match401k) OVER (PARTITION BY c.id ORDER BY c.checkDate) AS YTD401KMatch 
INTO 
#YTD401K 
FROM 
#Contributions c 
FULL JOIN 
#YTDGross yg ON 
yg.co = c.co AND yg.id = c.id AND yg.checkDate = c.checkDate 
+0

如果您要使用存儲過程,您可能會具有更好的可讀性。 – zedfoxus

+1

可以使用嵌套子查詢。或者可以使用基本計算創建視圖,然後將查詢放在視圖上。 – Glenn

回答

0

您可以用recursive CTE做到這一點。爲了簡單起見,我已經改變了你的名字,但基本的想法是這樣的:首先,將你的日期轉換爲連續的id(爲每個人),以便找到下一個簡單的。然後從頭開始,計算應該有點不同(前一天沒有)。然後在第二天添加,這次用一般的計算。沖洗並重復。

WITH Ids AS 
(
    SELECT 
     t.Val, 
     t.Person, 
     t.Day, 
     ROW_NUMBER() OVER -- consecutive ids 
     (
     PARTITION BY t.Person -- for each person 
     ORDER BY t.Day ASC -- in order of dates 
     ) AS DayId 
    FROM Tbl t 
) 
, RecCte AS 
(
    -- base case: first day for each person 
    SELECT 
     i.Val, 
     i.Person, 
     i.Day, 
     i.DayId, 
     (10.0-i.Val)/2.0 AS Calc, -- initial calculation 
     CAST(0 AS REAL) AS PrevCalc -- placeholder 
    FROM Ids i 
    WHERE i.DayId = 1 -- first day 

    UNION ALL 

    -- recursive case: later days 
    SELECT 
     n.Val, 
     n.Person, 
     n.Day, 
     n.DayId, 
     (10.0 - n.Val - p.Calc)/2 AS Calc, -- the general calculation 
     p.Calc AS PrevCalc -- copy value for reference 
    FROM Ids n -- next day 
    INNER JOIN RecCte p -- prev day 
     ON n.Person = p.Person 
     AND n.DayId = p.DayId+1 -- consecutive ids 
) 
    SELECT * 
    FROM RecCte a 
    ORDER BY a.Person ASC, a.Day ASC 
;