2009-05-21 61 views
1

我簡單地定義爲EOMDate(日期時間),丹達(浮動),優惠券(浮動),EarnedIncome(浮動)TSQL數學在表

04/30/2008, 20187.5,17812.5,NULL 
05/31/2008, 24640.63, 22265.63, NULL 
06/30/2008, 2375, 26718.75,NULL 

什麼我想一個@variabletable do是在表填充之後,我需要返回並計算EarnedIncome字段來填充它。 該公式是當前月份的DandA減去前一個月的DandA加上優惠券。 我遇到麻煩的是我該如何更新?因此,對於6/30,價值應該是4453.12(2375-24640.63)+26718.75

我會很高興地把頭上的泡吧解決。謝謝。另外,如果可能的話,在MS SQL2005下運行,因此可以使用任何CTE ROW_OVER類型的解決方案。

回答

1

您將需要使用這樣的子查詢:

UPDATE @variabletable v1 
SET EarnedIncome = DandA 
- (SELECT DandA FROM @variabletable v2 WHERE GetMonthOnly(DATEADD(mm, -1, v2.EOMDate)=GetMonthOnly(v1.EOMDate)) 
+ Coupon 

而我利用這個輔助功能的

DROP FUNCTION GetMonthOnly 
GO 
CREATE FUNCTION GetMonthOnly 
(
    @InputDate DATETIME 
) 
RETURNS DATETIME 
BEGIN 
    RETURN CAST(CAST(YEAR(@InputDate) AS VARCHAR(4)) + '/' + 
       CAST(MONTH(@InputDate) AS VARCHAR(2)) + '/01' AS DATETIME) 
END 
GO 
+0

已經有了equivavant日期功能,但這個答案讓我指出了正確的方向,謝謝! – 2009-05-21 15:54:08

-1

有可能是一種方式,一個語句要做到這一點,但在這種情況下,我傾向於設置一個遊標遍歷每行,計算該行的新EarnedIncome字段,更新行,然後移動到下一行。

例:

DECLARE @EOMDateVal DATETIME 
DECLARE @EarnedIncomeVal FLOAT 

DECLARE updCursor CURSOR FOR 
    SELECT EOMDate FROM @variabletable 

OPEN updCursor 

FETCH NEXT FROM updCursor INTO @EOMDateVal 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    // Compute @EarnedIncomeVal for this row here. 
    // This also gives you a chance to catch data integrity problems 
    // that would cause you to fail the whole batch if you compute 
    // everything in a subquery. 

    UPDATE @variabletable SET EarnedIncome = @EarnedIncomeVal 
     WHERE EOMDate = @EOMDateVal 

    FETCH NEXT FROM updCursor INTO @EOMDateVal 
END 
CLOSE updCursor 
DEALLOCATE updCursor 
0

您可以使用子查詢來進行測算,唯一的問題是你怎麼用第一個月做,因爲沒有以前丹達值。這裏我使用isnull將其設置爲0。查詢看起來像

Update MyTable 
Set EarnedIncome = DandA + Coupon - IsNull( Select Top 1 DandA 
              From MyTable2 
              Where MyTable.EOMDate > MyTable2.EOMDate 
              Order by MyTable2.EOMDate desc), 0) 

這還假定你只需要每月一條記錄在每個表中,並有are't個月之間的任何間隙。

1

肯定有不少方法可以做到這一點。你會發現利弊取決於你的數據集有多大,以及其他因素。

這裏是我的建議......

Declare @table as table 
(
    EOMDate DateTime, 
    DandA float, 
    Coupon Float, 
    EarnedIncome Float 
) 

Insert into @table Values('04/30/2008', 20187.5,17812.5,NULL) 
Insert into @table Values('05/31/2008', 24640.63, 22265.63, NULL) 
Insert into @table Values('06/30/2008', 2375, 26718.75,NULL) 


--If we know that EOMDate will only contain one entry per month, and there's *always* one entry a month... 
Update @Table Set 
EarnedIncome=DandA- 
(Select top 1 DandA 
from @table t2 
where t2.EOMDate<T1.EOMDate 
order by EOMDate Desc)+Coupon 
From @table T1 
Select * from @table 

--If there's a chance that there could be more per month, or we only want the values from the previous month (do nothing if it doesn't exist) 

Update @Table Set 
EarnedIncome=DAndA-(
Select top 1 DandA 
From @table T2 
Where DateDiff(month, T1.EOMDate, T2.EOMDate)=-1 
Order by EOMDate Desc)+Coupon 
From @Table T1 

Select * from @table 
--Leave the null, it's good for the data (since technically you cannot calculate it without a prior month). 

我喜歡第二種方法最好,因爲如果存在對上月的紀錄只會計算。

(以下內容添加到上面的腳本看出差別)

--Add one for August 
Insert into @table Values('08/30/2008', 2242, 22138.62,NULL) 


Update @Table Set 
EarnedIncome=DAndA-(
     Select top 1 DandA 
     From @table T2 
     Where DateDiff(month, T1.EOMDate, T2.EOMDate)=-1 
     Order by EOMDate Desc 
)+Coupon 
From @Table T1 

--August is Null because there's no july 
Select * from @table 

這是你想要什麼做的所有的事。 使用記錄直接進行當前記錄(不管日期),還是隻使用當前記錄前一個月的記錄。

對不起格式... Stackoverflow.com的答案編輯器,我不在一起玩。

:D