1

完全にエレガントな解決策があると信じている問題がありますが、助けが必要です。

だから私は人のテーブルと数値を持っています。それに加えて、その値 (1 人あたり) を複数のアカウントに分割するルールを含むテーブルがあり、ルールは最大値または値のパーセンテージのいずれかです。

これは、これらの表の簡略版です。

Persons(PersonID int, Value decimal)

Account(AccountID int, PersonID int)

Distribution(AccountID int, MaxValue decimal Null, Percentage decimal null)

ある時点で、これらの数値を 3 番目のテーブルに分割する必要があります。このテーブルには、アカウントとそのアカウントに分割された値が保持されます。

AccountValues(AccountID int, AccountValue decimal)

アカウント数(1人あたり)は固定ではありません。分布表では、両方の分布値が 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. 最も洗練されていない - 1 人あたりのアカウントの最大数を数え、その回数だけループを実行します。2. カーソル - おそらく最良の方法は? 3. CTE 再帰 (私は何も知らない)

4

1 に答える 1

0

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 ( DisbValues) により、パーセンテージで考える必要がなくなります (特定のアカウントを満足させるために、残りの部分ではなく、利用可能な合計値のパーセンテージで作業していると想定しています)。次に、2 番目の CTE ( CumulativeValues) は、以前のアカウントに入力する必要があるすべての値を合計します。

その後、コメントで示されているように、最後のクエリで 3 つのケースに分類できます。

于 2012-09-10T08:52:12.737 に答える