Tsql T-SQL将一个数值拆分为多个帐户的优雅解决方案

Tsql T-SQL将一个数值拆分为多个帐户的优雅解决方案,tsql,division,Tsql,Division,我有一个问题,我相信有一个完美的解决方案,但希望得到一些帮助 所以我有一张人员表和一个数值。除此之外,还有一个表,其中包含将每个人的值划分为多个帐户的规则,规则可以是最大值或值的百分比 这是这些表的简化版本 Persons(PersonID int, Value decimal) Account(AccountID int, PersonID int) Distribution(AccountID int, MaxValue decimal Null, Percentage decimal

我有一个问题,我相信有一个完美的解决方案,但希望得到一些帮助

所以我有一张人员表和一个数值。除此之外,还有一个表,其中包含将每个人的值划分为多个帐户的规则,规则可以是最大值或值的百分比

这是这些表的简化版本

Persons(PersonID int, Value decimal)

Account(AccountID int, PersonID int)

Distribution(AccountID int, MaxValue decimal Null, Percentage decimal null)
在某个时刻,我需要将这些数值划分到第三个表中——该表包含帐户和被划分到该帐户的值

AccountValues(AccountID int, AccountValue decimal)
每个人的账户数量不是固定的。在分布表中-如果两个分布值都为null-所有剩余值都将进入该帐户。 分配的顺序是根据他们的ID

数据可能是这样的

Persons  table
PersonID    Value
    1            1000,00
    2            2000,00
    3            5000,00
    4            500,00

Accounts table
AccountID   PersonID
1            1
2            1
3            2
4            2
5            2
6            3
7            3
8            4
9            4
10           4

Distribution table
AccountID    MaxValue    Percentage
1            500,00          null
2            null            null
3            null            0,5
4            null            0,2
5            null            null
6            1000,00         null
7            null            null
8            2000,00         null
9            null            0,2
10           null            null
对于T-SQL来说还是有点陌生,所以需要帮助找到最简单、最高效的解决方案

所以现在我在考虑3种可能的解决方案。 1.最少优雅-计算每个人的最大帐户数,并多次循环。 2.光标-也许是最好的方式?
3.关于CTE递归,我一无所知

我使用了一个CTE。也许有一种更聪明的方法来计算总数,但我认为这是可行的

数据设置:

declare @Persons table (PersonID int not null,Value decimal(18,4) not null)
insert into @Persons(PersonID,Value) values
(1,1000.00),
(2,2000.00),
(3,5000.00),
(4,500.00)

declare @Accounts table (AccountID int not null,PersonID int not null)
insert into @Accounts(AccountID,PersonID) values
(1,1),
(2,1),
(3,2),
(4,2),
(5,2),
(6,3),
(7,3),
(8,4),
(9,4),
(10,4)

declare @Distribution table (AccountID int not null,MaxValue decimal(18,4) null,Percentage decimal(6,5) null)
insert into @Distribution (AccountID,MaxValue,Percentage) values
(1,500.00,null),
(2,null,null),
(3,null,0.5),
(4,null,0.2),
(5,null,null),
(6,1000.00,null),
(7,null,null),
(8,2000.00,null),
(9,null,0.2),
(10,null,null)

declare @AccountValues table (AccountID int not null,Value decimal(18,4) null)
实际查询:

;With DisbValues as (
    select
        a.AccountID,
        p.PersonID,
        CASE
            WHEN d.MaxValue is not null then d.MaxValue
            WHEN d.Percentage is not null then d.Percentage * p.Value
        END as Value,
        p.Value as TotalAvailable
    from
        @Distribution d
            inner join
        @Accounts a
            on
                d.AccountID = a.AccountID
            inner join
        @Persons p
            on
                a.PersonID = p.PersonID
), CumulativeValues as (
    select
        AccountID,
        PersonID,
        Value,
        COALESCE((select SUM(Value) from DisbValues d2 where d2.PersonID = d.PersonID and d2.AccountID < d.AccountID),0) as PrevValue,
        TotalAvailable
    from
        DisbValues d
)
insert into @AccountValues (AccountID,Value)
select
    AccountID,
    CASE WHEN PrevValue < TotalAvailable THEN
        CASE WHEN PrevValue + Value < TotalAvailable THEN Value --Entirely satisfied
        ELSE TotalAvailable - PrevValue --Partially satisfied
        END
    ELSE
        0 --Not satisfied
    END
from CumulativeValues
第一个CTE值消除了从百分比角度考虑的需要。我假设我们使用的是可用总价值的百分比,而不是试图满足特定帐户时剩余的百分比。然后,第二个CTE累积值将早期账户需要填写的所有值相加


然后,在最后一个查询中,我们可以将事情分解为3种情况,如注释所示。

游标几乎从来都不是最好的解决方案其他一个或两个表中是否缺少PersonID?我不太明白你的叙述。如果您可以添加5到10行之间的样本数据,显示一些变化和预期结果,我可以试一试。@user1659425-没问题。它只有一个问题——我刚刚回来看它,我自己也不知道它是如何处理空值的。一旦我自己解决了这个问题,我可能会添加一个解释