sql - 如何在没有游标的情况下将值分布在多行中?

标签 sql tsql sql-server-2005

有没有一种简单的方法可以将值分布在多行中?

例如,我的表包含

Type      Invoiced    Paid    Current
Charge    100         0       100
Charge    100         0       100
Charge    100         0       100
Payment   0         250       0
Payment   0          25       0

The data is imported this way, but I need to populate the Current and Paid columns with whatever they should be for that transaction based on the payment transactions that were also imported.

Is there an easy way to write a query to determine the balance for the Current column for each record?

For example, the 250 would apply 100 for the first two records and 50 to the next two, and the 25 would get applied to the last one, so the end result after updating the Current balance in my table should be:

Type      Invoiced    Paid    Current
Charge    100         100     0
Charge    100         100     0
Charge    100          75     25
Payment   0           250     0
Payment   0            25     0

I'd ideally like to do this with a single query instead of using a cursor to process each item individually. I've been trying to do it by using the Row_Number() function and joining two subqueries, but I know I'm missing something here

Here was my first attempt, which resulted in getting the running total of the current balance

;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

结果:

已开具发票的已付现款
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

然后我需要将此值应用于每条记录,直到运行总数大于支付的总数。

为此,我修改了我的运行总查询,因此它只汇总费用而不是汇总费用和付款
;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

并将其加入到付款查询中,所以现在我有一堆包含总付款金额、直到该记录的运行总费用以及当前记录的费用金额的行。

从那里,我只需要一个 CASE语句来确定费用是全额支付、部分支付还是根本没有支付,并使用一点数学计算出PaidCurrent记录
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

而最终的结果正是我想要的。只需要通过 Id 将其加入到实际数据表中列,并更新 PaidCurrent值(value)观:)

Id AccountId 已开票已付当前
1 1 100 100 0
2 1 100 100 0
3 1 100 75 25

关于sql - 如何在没有游标的情况下将值分布在多行中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12303795/

相关文章:

performance - View 和表在性能上的区别

sql - 从 Node.JS 连接到 SQL Azure

mysql - 我试图弄清楚在多少种电影类别中,电影更换成本和租金之间的平均差异大于 15

sql - 使用有限的数据估算每个标签(或标签组)每月的页面浏览量?

sql - TSQL - 如何查找列是否有空格 char(32)?

php - 根据表数据有条件地执行SQ​​L查询/语句

sql - Oracle/PostgreSQL 中的序列在插入语句中没有 ID

sql - 在postgresql中打印一个变量的值

sql - 仅在 SQL Server 2005 中存储日期

sql - 与 GO 语句、未提交事务和更改过程混淆