2012-06-12 50 views
1

我的數據庫關於現金餘額,交易和隔夜頭寸使我的用戶。日期也有差距。T-SQL CTE適用於每個日期的百分比公式和總計值

使用CTE我選擇了兩張包含現金和交易餘額總和[cashtrade_sum]和職位[pos_sum]的表格。下面是一個示例:

cashtrade_sum 
------------- 
2012-01-30 10000.00 
2012-03-19 9868.99 
2012-03-20 9839.02 
2012-03-21 10476.10 
2012-03-22 0.00 
2012-03-23 10102.81 
2012-03-26 10314.76 
2012-03-27 11037.40 
2012-03-28 9887.76 
2012-03-29 9234.28 
2012-03-30 8718.67 
2012-04-02 8396.65 
2012-04-03 0.00 
2012-04-12 0.00 
2012-05-18 1796.78 

pos_sum 
------- 
2012-03-22 17628.00 
2012-03-23 0.00 
2012-03-28 373.24 
2012-03-29 0.00 
2012-04-03 20835.00 
2012-04-04 20736.00 
2012-04-05 20268.00 
2012-04-06 20268.00 
2012-04-07 20268.00 
2012-04-08 20268.00 
2012-04-09 20412.00 
2012-04-10 19998.00 
2012-04-11 18999.00 
2012-04-12 11465.00 
2012-04-13 10975.00 
2012-04-14 10975.00 
2012-04-15 10975.00 
2012-04-16 9750.00 

我有依賴於前面的可用日期[cashtrade_sum]值佣金公式應用到每個[pos_sum]值。結果應添加到當前[cashtrade_sum]日期。所以當前日期[cashtrade_sum]取決於之前的彙總或減法。

爲了清楚起見,簡單地說明如何從當前[pos_sum]大於昨天[cashtrade_sum]或最大上一個可用日期的[cashtrade_sum]中減去每個[pos_sum]值的5%。假設[cashtrade_sum]的價值已在上一步中修改。

請幫助它在沒有INSERT的情況下在CTE上進行操作,並分別獲得5%的佣金值。像這樣:

results 
------- 
        commission cash 
2012-01-30      10000.00 
2012-03-19      9868.99 
2012-03-20      9839.02 
2012-03-21      10476.10 
2012-03-22   881.4  9594.70 
2012-03-23   0.00  9594.70 
2012-03-28   0.00  9594.70 
2012-03-29   0.00  9594.70 
2012-04-03   1041.75  8552.95 
2012-04-04   1036.80  7516.12 
2012-04-05   1013.40  6502.72 
... 

最好填寫日期差距,但這只是一個例子。真正的公式要複雜得多。

在SQL Server 2008 R2上運行。

謝謝!

+2

你能展示實際期望的結果是什麼樣子嗎?這樣可以更輕鬆,更有趣地攻擊問題,而不是反向設計一個單詞問題,並猜測你期望輸出什麼...... –

回答

2

好的,所以,這讓我感到困惑。我想我明白你要找的是以下內容:

對於每一個給定的一天,外地「現金」的定義是指在cashtrade_sum值 ,如果存在的話,或計算值取 cashtrade_sum從記錄的最後日期開始,扣除所有 先前的佣金值。如果pos_sum大於前一天的 現金,則將每個日期的佣金定義爲當天pos_sum的5% ;否則,佣金爲$ 0。

但是當我真正實施了,該數據並不像例子中的任何結果,您提供的,因爲你有cashtrade_sum值28 3月23日和29,似乎有在結果沒有反映。相反,一旦支付了任何佣金,似乎只要忽略了cashtrade_bal中的所有後續條目,並且只通過支付佣金來減少現金字段。

所以,我實現了,而不是真正理解爲什麼。我還添加了一個日曆表來執行你提到的日期插值,所以你每天都會得到值。

CREATE TABLE #cashtrade_sum 
(
    recdate date, 
    balance money 
) 

create table #pos_sum 
(
    recdate date, 
    position money 
) 

INSERT INTO #cashtrade_sum 
VALUES 
    ('2012-03-01', 10000.00), 
    ('2012-03-19', 9868.99), 
    ('2012-03-20', 9839.02), 
    ('2012-03-21', 10476.10), 
    ('2012-03-22', 0.00), 
    ('2012-03-23', 10102.81), 
    ('2012-03-26', 10314.76), 
    ('2012-03-27', 11037.40), 
    ('2012-03-28', 9887.76), 
    ('2012-03-29', 9234.28), 
    ('2012-03-30', 8718.67), 
    ('2012-04-02', 8396.65), 
    ('2012-04-03', 0.00), 
    ('2012-04-12', 0.00), 
    ('2012-05-18', 1796.78) 

INSERT INTO #pos_sum 
VALUES 
    ('2012-03-22', 17628.00), 
    ('2012-03-23', 0.00), 
    ('2012-03-28', 373.24), 
    ('2012-03-29', 0.00), 
    ('2012-04-03', 20835.00), 
    ('2012-04-04', 20736.00), 
    ('2012-04-05', 20268.00), 
    ('2012-04-06', 20268.00), 
    ('2012-04-07', 20268.00), 
    ('2012-04-08', 20268.00), 
    ('2012-04-09', 20412.00), 
    ('2012-04-10', 19998.00), 
    ('2012-04-11', 18999.00), 
    ('2012-04-12', 11465.00), 
    ('2012-04-13', 10975.00), 
    ('2012-04-14', 10975.00), 
    ('2012-04-15', 10975.00) , 
    ('2012-04-16', 9750.00) 

CREATE TABLE #cal 
(
    caldate date 
) 

DECLARE @CurDate date = '2012-03-01'; 

while @CurDate < '2012-05-01' 
BEGIN 
    INSERT INTO #cal 
    VALUES(@CurDate) 

    SELECT @CurDate = DATEADD(day,1,@CurDate) 
END 

SELECT * FROM #cashtrade_sum; 
SELECT * FROM #pos_sum; 
SELECT * FROM #cal; 

WITH calc AS 
(
    SELECT caldate AS calcdate, CAST(0 AS money) AS commission, balance AS dailybal, balance AS runningbal, CAST(0 as money) as position, 
     0 as commpaid 
    FROM #cal 
     left join #cashtrade_sum 
      on #cal.caldate = #cashtrade_sum.recdate 
    WHERE caldate = (SELECT MIN(caldate) FROM #cal) 

    UNION ALL 

    SELECT #cal.caldate, 
     comm.commission, 
     cts.balance, 
     case 
      when prev.commpaid = 1 OR comm.commission > 0 
       then prev.runningbal - comm.commission 
      else 
       ISNULL(cts.balance, prev.runningbal - comm.commission) 
     END, 
     ps.position, 
     CASE WHEN comm.commission > 0 then 1 else prev.commpaid end 
    FROM #cal 
     outer apply (SELECT * FROM #pos_sum where #cal.caldate = #pos_sum.recdate) ps 
     outer apply (SELECT * FROM #cashtrade_sum where #cal.caldate = #cashtrade_sum.recdate) cts 
     cross apply (select runningbal, commpaid from calc where calcdate = DATEADD(DAY, -1, #cal.caldate)) prev 
     cross apply (select CASE WHEN prev.runningbal < ps.position THEN cast(ps.position * 0.05 as money) ELSE cast(0 as money) END AS commission) comm 
) 
SELECT calcdate, commission, runningbal FROM calc 

drop table #cashtrade_sum 
drop table #pos_sum 
drop table #cal 

注意,我改變了第一次約會從一月到三月,因爲SQL Server有一個默認的遞歸限制會殺死這個遞歸CTE數據後100天死亡。爲了使這項工作更長時間,您需要提高遞歸限制。

我仍然認爲你或我對結果應該是什麼樣子感到困惑,但這確實會產生你要求的結果。

+0

是的,固定日期聲明和循環的技術相當混亂。我發現這一個:SELECT ... DATEADD(day,val.number,trd.tradedate)... FROM ... CROSS JOIN(SELECT number FROM master.dbo.spt_values WHERE'P'= type AND number <= DATEDIFF(day,(SELECT MIN(tradedate)FROM trades),GETDATE() - 1))AS val – 84RR1573R

+0

但是我想到了CROSS APPLY。謝謝!我會試試真實的數據。 – 84RR1573R

+0

許多人再次感謝!任務聽起來很奇怪。我用更高級的公式重寫你的解決方案,並得到我想要的。 – 84RR1573R