Rac*_*hel 5 sql t-sql sql-server-2005
有没有一种简单的方法可以将值分布在多行中?
例如,我的表包含
类型已开票已付电流 充电 100 0 100 充电 100 0 100 充电 100 0 100 付款 0 250 0 付款 0 25 0
数据是通过这种方式导入的,但我需要根据也导入的付款交易为该交易填充Current和Paid列。
有没有一种简单的方法来编写查询来确定Current每条记录的列的余额?
例如,250 会将 100 应用于前两条记录,50 应用于接下来的两条记录,而 25 将应用于最后一条,因此更新Current表中的余额后的最终结果应该是:
类型已开票已付电流 充电 100 100 0 充电 100 100 0 充电 100 75 25 付款 0 250 0 付款 0 25 0
理想情况下,我希望使用单个查询来执行此操作,而不是使用游标来单独处理每个项目。我一直在尝试通过使用Row_Number()函数并加入两个子查询来做到这一点,但我知道我在这里遗漏了一些东西
这是我的第一次尝试,结果得到了当前余额的运行总数
;with cte(invoiced, paid, current)
as (
select invoiced, paid, current
, row_number() over (order by datecreated)
from mytable
)
select t1.invoiced, t1.paid, sum(t2.invoiced - t2.paid) as [current]
from cte as t1
join cte as t2 on t1.number = t2.number and t2.rownum <= t1.rownum
group by t1.uid, t1.number, t1.rownum
order by t1.rownum
Run Code Online (Sandbox Code Playgroud)
结果:
已开具发票的已付现款 100 0 100 100 0 200 100 0 300 0 250 50 0 25 25
我确信有办法做到这一点,但现在我的大脑似乎受到了打击,拒绝提出解决方案。
我想我找到了解决方案
首先,我不需要将付费交易链接到已开票交易,因此我只需要所有付款的总和
select accountid, sum(paid)
from mytable
where type = 'Payment'
group by accountid
Run Code Online (Sandbox Code Playgroud)
然后我需要将此值应用于每条记录,直到运行总额大于支付总额。
为此,我修改了运行总计查询,使其仅对费用求和,而不是对费用和付款求和
;with cte(id, accountid, invoiced, paid, current)
as (
select id, accountid, invoiced, paid, current
, row_number() over (order by datecreated)
from mytable
where type = 'Charge'
)
select t1.id, t1.accountid, t1.invoiced, sum(t2.invoiced) as [runningTotalOfCharges]
from cte as t1
join cte as t2 on t1.number = t2.number and t2.rownum <= t1.rownum
group by t1.id, t1.accountid, t1.invoiced
Run Code Online (Sandbox Code Playgroud)
并将其加入到付款查询中,所以现在我有一堆行,其中包含总付款金额、截至该记录的费用运行总额以及当前记录的费用金额。
从那里,我只需要一份CASE声明来确定费用是否已全额支付、部分支付或根本未支付,并使用一点数学来计算出Paid和Current记录
select charged.Id, charged.AccountId, charged.Invoiced
-- Use Case statements to determine if this payment is fully paid, partially paid,
-- or not paid at all, then determine Current and Paid based on that
, case when totalpaid - runningtotal >= 0 then invoiced
when invoiced > abs(totalpaid - runningtotal) then invoiced + totalpaid - runningtotal
else 0 end as [Paid]
, case when totalpaid - runningtotal >= 0 then 0
when invoiced > abs(totalpaid - runningtotal) then abs(totalpaid - runningtotal)
else invoiced end as [Current]
from
(
-- Running total query from above
select t1.id, t1.accountid, t1.invoiced, sum(t2.invoiced) as [runningtotal]
from cte as t1
join cte as t2 on t1.number = t2.number and t2.rownum <= t1.rownum
group by t1.id, t1.accountid, t1.invoiced
) as charged
inner join (
-- Total Paid query from above
select accountid, sum(paid) as totalpaid
from mytable
where type = 'Payment'
group by accountid
) as paid on charged.number = paid.number
Run Code Online (Sandbox Code Playgroud)
而最终的结果就是我想要的。只需要通过Id列将其连接到实际数据表,并更新Paid和Current值:)
ID AccountId 已开具发票 已付款 当前 1 1 100 100 0 2 1 100 100 0 3 1 100 75 25
| 归档时间: |
|
| 查看次数: |
3266 次 |
| 最近记录: |