Sql server T-SQL CTE应用百分比公式并汇总每个日期的值

Sql server T-SQL CTE应用百分比公式并汇总每个日期的值,sql-server,tsql,sum,common-table-expression,Sql Server,Tsql,Sum,Common Table Expression,我的数据库是关于我的用户的现金余额、交易和隔夜头寸的。日期也有差距 使用CTE,我选择了两个包含现金和交易余额总和[cashtrade\u sum]和头寸[pos\u 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 20

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

使用CTE,我选择了两个包含现金和交易余额总和[cashtrade\u sum]和头寸[pos\u 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\u sum]值,对每个[pos\u sum]值应用佣金公式。结果应添加到当前[现金交易金额]日期。因此,当前日期[现金交易金额]取决于之前的汇总或减法

为了说明问题,简单地说,如果当前[pos_sum]大于昨天的[cashtrade_sum]或之前的最大可用日期,那么如何从[cashtrade_sum]中减去每个[pos_sum]值的5%。假设[cashtrade_sum]的值已在上一步中修改

请帮助它在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
...
填补日期空白也更好,但这只是一个例子。真正的公式要复杂得多

在SQLServer2008R2上运行


谢谢大家!

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

对于每一天,“现金”字段定义为 现金交易金额,如果存在,或计算得出 现金交易记录上最后一个日期的总和,并减去所有 以前的佣金价值。每个日期的佣金定义为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
创建表#现金交易#金额
(
记录日期,
平衡货币
)
创建表#pos#sum
(
记录日期,
头寸资金
)
插入#现金交易#金额
价值观
('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)
插入#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)
创建表格#校准
(
计算日期
)
声明@CurDate日期='2012-03-01';
而@CurDate<'2012-05-01'
开始
插入到#cal中
值(@CurDate)
选择@CurDate=DATEADD(天,1,@CurDate)
结束
从#现金交易#金额中选择*;
选择*FROM#pos#sum;
选择*FROM#cal;
以calc为例
(
选择caldate作为calcdate,CAST(0作为货币)作为佣金,余额作为dailybal,余额作为runningbal,CAST(0作为货币)作为头寸,
0作为预付款
从#cal
左联接#现金交易#总和
on#cal.caldate=#cashtrade_sum.recdate
其中caldate=(从#cal中选择MIN(caldate)
联合所有
选择#cal.caldate,
通信委员会,
cts.balance,
案例
当预付佣金=1或佣金>0时
然后是上一个runningbal-通信委员会
其他的
ISNULL(cts.balance,上一个runningbal-通讯佣金)
完,,
私人秘书职位,
如果通信佣金>0,则1 else prev.COMMPAYED end
从#cal
外部应用(选择*自#pos#u sum,其中#cal.caldate=#pos#u sum.recdate)ps
外部应用(从#cashtrade_sum中选择*,其中#cal.caldate=#cashtrade_sum.recdate)cts
交叉应用(选择runningbal,commpaid from calc,其中calcdate=DATEADD(DAY,-1,#cal.caldate))prev
交叉应用(当上一个runningbal
请注意,我将第一个日期从1月改为3月,因为SQL Server有一个默认的递归限制,该限制将在100天的数据之后终止此递归CTE。要使其在更长的时间内工作,您需要提高递归限制


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

您能展示实际期望的结果吗?这使得解决这个问题变得更容易、更有趣,而不是对一个单词问题进行反向工程并猜测您对输出的期望……是的,固定日期声明和循环的技术相当混乱。我发现了这个:选择。。。DATEADD(日期、val.number、trd.tradedate)。。。从…起交叉连接(从master.dbo.spt_值中选择数字,其中'P'=类型和数字,但我得到了交叉应用的想法。谢谢!我将尝试实际数据。许多