将发票总计拆分为多行,但拆分始终等于总计

问题描述 投票:0回答:1
Create Table #Invoices
(
    InvoiceID int,
    Amount money,
    ProjectID int
)   
insert into #Invoices
(
    InvoiceID,
    Amount,
    ProjectID
)
select
    1,
    100,
    1
union all
select
    2,
    100,
    2
union all
select
    3,
    100,
    3
union all
select
    4,
    100,
    4

Create Table #Projects
(
    ProjectID int,
    AccountCode int
)
insert into #Projects
(
    ProjectID,
    AccountCode
)
select
    1,
    '12345'
union all
select
    2,
    '12345'
union all
select
    2,
    '7890'
union all
select
    3,
    '800'
union all
select
    3,
    '234'
union all
select
    3,
    '987'
union all
select
    4,
    '800'
union all
select
    4,
    '234'
union all
select
    4,
    '987'
union all
select
    4,
    '2579'

这是几年前这个问题的后续问题 将 1 行分成 2 行,占总数的百分比

我有上面的示例数据,我想做的是拆分发票行 根据 AccountCode 分成多行,但计算分割,所以如果有 2个相关AccountCodes,金额应分割50%/50%,如果有3个,则分割 33.3%/33.3%/33.3%,但一行是 34,所以它与总数持平。等等等等。

这是我到目前为止整理的一个查询:

select 
    I.*,
    P.AccountCode,
    I.Amount / count(I.InvoiceID) over (partition by P.ProjectID) as SplitAmount
from 
    #Invoices I
Inner Join #Projects P on 
    I.ProjectID = P.ProjectID
order by
    I.InvoiceID

它似乎在 SplitAmount 方面有效,但有一个问题。发票ID 3 包含三个值 33.33,等于 99.99。我怎样才能确保分裂会 无论分割次数如何,总金额始终等于?

这是一张显示我想要的最终结果的表格。我已将其中一行更改为 33.34 所以我得到了 100 结果,但请记住,该金额可以是任何金额。

发票ID 金额 项目ID 账号代码 分割金额
1 100.00 1 12345 100.00
2 100.00 2 12345 50.00
2 100.00 2 7890 50.00
3 100.00 3 800 33.33
3 100.00 3 234 33.33
3 100.00 3 987 33.34
4 100.00 4 800 25.00
4 100.00 4 234 25.00
4 100.00 4 987 25.00
4 100.00 4 2579 25.00
sql sql-server t-sql sql-server-2017
1个回答
0
投票

总结

SplitAmount
并用
#Invoices.Amount
进行验证,并将任何差异调整到其中一行。

在计算

round()
 时,您可能需要 
SplitAmount

保留 2 位小数
select *,
       SplitAmount 
       + case when rn = 1 
              then i.Amount - sum  (i.SplitAmount) 
                              over (partition by i.ProjectID)
              else 0
              end  as AdjustedSplitAmount
from
(
  select 
      I.*,
      P.AccountCode,
      round(I.Amount / count(I.InvoiceID) over (partition by P.ProjectID), 2) as SplitAmount,
      row_number() over (partition by P.ProjectID order by p.AccountCode) as rn
  from 
      #Invoices I
  Inner Join #Projects P on 
      I.ProjectID = P.ProjectID
) i
© www.soinside.com 2019 - 2024. All rights reserved.