1

我的数据库是关于我的用户的现金余额、交易和隔夜头寸。日期也有差距。

使用 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] 取决于之前的汇总或减法。

为了清楚起见,简单地说,如何从 [cashtrade_sum] 中减去每个 [pos_sum] 值的 5%,其中当前 [pos_sum] 大于昨天 [cashtrade_sum] 或最大上一个可用日期。假设 [cashtrade_sum] 的值已在上一步中修改。

请帮助它在没有 INSERTions 的情况下即时制作 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 上运行。

谢谢!

4

1 回答 1

2

好的,所以,这让我很困惑。我想我明白你在找什么,如下所示:

对于每一天,“现金”字段被定义为 cashtrade_sum 中的值(如果存在),或者从记录的最后一个日期计算出的 cashtrade_sum 值并减去所有先前的佣金值。如果pos_sum大于前一天的现金,则每个日期的佣金定义为当天pos_sum的5%;否则,佣金为 0 美元。

但是当我实际实施时,数据看起来与您提供的示例结果完全不同,因为您有 3 月 23 日、28 日和 29 日的 cashtrade_sum 值,这些值似乎没有反映在结果中。相反,似乎只要支付了任何佣金,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

请注意,我将第一个日期从 1 月更改为 3 月,因为 SQL Server 具有默认递归限制,该限制将在 100 天的数据后终止此递归 CTE。要使这项工作更长时间,您需要提高递归限制。

我仍然认为您或我对结果的实际外观感到困惑,但这确实会产生您要求的结果。

于 2012-06-12T04:51:16.507 回答