Sql server T-SQL CTE应用百分比公式并汇总每个日期的值
我的数据库是关于我的用户的现金余额、交易和隔夜头寸的。日期也有差距 使用CTE,我选择了两个包含现金和交易余额总和[cashtrade\u sum]和头寸[pos\u sum]的表。以下是一个示例: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
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'=类型和数字,但我得到了交叉应用的想法。谢谢!我将尝试实际数据。许多