如何在不同阶段计算每个ID的总付费金额,并在SQL Server 2012中每个阶段后减少付费金额

时间:2016-04-20 09:23:47

标签: sql sql-server-2012 common-table-expression

我有两张表TableATableB

  • TableA将总需求(列名称 - >数量)拆分为各行。
  • TableB有供应号码(列名称 - >数量)。

我想拆分供应数字,并针对每个ID(列名称 - >数字)分配TableA中的每一行。

TableATableB的示例数据如下:

表A

row number  amount
-------------------
1     x       10
2     y        5
3     z       120
4     z        80
5     z         5

表B

number  amount
---------------
  x       5 
  y       15
  z       200

必需的输出是:

row number  amount  paid
-------------------------
1     x        10     5
2     y         5     5
3     z       120   120
4     z        80    80
5     z         5     0

截至目前,我们正在使用下面提到的代码,这些代码非常难看并且没有提供良好的性能,因为我们使用递归cte来完成这项工作,因为我们的系统是SQL Server 2008 R2我们别无选择,但现在我们的软件已升级到SQL Server 2012,我知道使用sum函数和over by子句可以实现相同的功能。但是我不知道怎么做?

with cte as 
(
    select 
        a.row, a.number, a.amount,
        b.amount as total
    from 
        tableA as a
    left join 
        tableB as b on a.number = b.number
),
cte1 as 
(
    select 
        row, number, amount, total,
        case 
           when amount - total < 0 then amount else total 
        end as paid,
        case 
           when amount - total < 0 then amount else total 
        end as totalpaid
    from 
        cte
    where 
        row = 1

    union all

    select 
        b.row, b.number, b.amount, b.total,
        case
           when b.amount - (b.total - (case when b.number = a.number then a.totalpaid else 0 end)) < 0 then b.amount else (b.total - (case when b.number = a.number then a.totalpaid else 0 end)) end,
           case when b.amount - (b.total - (case when b.number = a.number then a.totalpaid else 0 end)) < 0 then b.amount else (b.total - (case when b.number = a.number then a.totalpaid else 0 end)) end + ((case when b.number = a.number then a.totalpaid else 0 end))
    from 
        cte1 as a
    inner join 
        cte as b on b.row = a.row + 1
)
select 
    row, number, amount, paid
from 
    cte1

有人能告诉我如何在SQL Server 2012中有效地编写上述代码吗?

提前致谢。

1 个答案:

答案 0 :(得分:3)

试试这段代码:

WITH cte as
(
    SELECT a.row,
        a.number, 
        a.amount,
        b.amount AS totalPaid,
        SUM(a.amount) OVER (PARTITION BY a.number ORDER BY row ROWS UNBOUNDED PRECEDING) AS totalAmount
            FROM (VALUES (1,'x',10),(2,'y',5),(3,'z',120),(4,'z',80),(5,'z',5)) AS a(row, number, amount)
            LEFT JOIN (VALUES ('x',5),('y',15),('z',200)) as b(number, amount) ON a.number = b.number
)
SELECT row, number, amount, CASE WHEN totalPaid >= totalAmount THEN amount ELSE CASE WHEN amount - totalAmount + totalPaid < 0 THEN 0 ELSE amount - totalAmount + totalPaid END END AS paid
    FROM cte;

请告诉我有关正确性和绩效改进的反馈意见。