数直線上の間隔としてあなたのドル金額の主なアイデア
と思います。請求書と支払いを正しい順序で、互いに隣接する行に配置します。(それらと交差)と共に間隔の両方のセットを入れ
請求書、受信機/送信者ID = 1
|----100---|----100---|--------200--------|----------->
0 100 200 400
ID 1 2 5
支払い、受信機/送信者ID = 1
|-50-|-45|-------------------------------------------->
0 50 95
ID 1 2
:
|----|---|-|----------|-------------------|----------->
0 50 95 100 200 400
の今、あなたが持っている間隔:
請求書
From To InvoiceID PaymentID
------------------------------------
0 50 1 1
50 95 1 2
95 100 1
100 200 2
200 400 5
、レシーバ/送信者ID = 2
|----100---|----100---|------------------------------->
0 100 200
ID 3 4
支払い、レシーバ/送信者ID = 2
|--95----|-----105----|------------------------------->
0 95 200
ID 3 4
両方のセットの間隔を合わせる(交差する裾):
|--------|-|----------|------------------------------->
0 95 100 200
は、今あなたが持っている間隔:()にも何もないことができ、最大で1枚の請求書と最大で1つのお支払いが可能これらの間隔のそれぞれについて
From To InvoiceID PaymentID
------------------------------------
0 95 3 3
95 100 3 4
100 200 4 4
。これらの各期間に対応する請求書と支払いを確認し、請求書と支払いの間のマッピングを取得します。各請求書の支払い間隔を合計すると、請求書の全額または一部が支払われたかどうかがわかります。
インボイスとペイメントの間隔の初期リストを作成することは、合計を実行することによって行われます。
SUM(Amount) OVER (PARTITION BY ReceiverId ORDER BY Priority
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS InvoiceInterval
SUM(Amount) OVER (PARTITION BY SenderId ORDER BY PaymentID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS PaymentInterval
これらの2つのセットを交差させることは簡単ですUNION
です。
各区間について、対応する請求書および支払いを見つける。それを行う簡単な方法の1つはOUTER APPLY
のサブクエリです。
これらをまとめてみましょう。
サンプルデータ
DECLARE @Invoice TABLE
(
[InvoiceId] [int] NOT NULL,
[ReceiverId] [int] NOT NULL,
[Amount] [numeric](19, 2) NOT NULL,
[Priority] [int] NOT NULL
);
DECLARE @Payment TABLE
(
[PaymentId] [int] NOT NULL,
[SenderId] [int] NOT NULL,
[Amount] [numeric](19, 2) NOT NULL
);
INSERT INTO @Invoice(InvoiceId,ReceiverId,Amount,Priority) VALUES
(1, 1, 100.00, 1),
(2, 1, 100.00, 2),
(3, 2, 100.00, 1),
(4, 2, 100.00, 2),
(5, 1, 200.00, 3);
INSERT INTO @Payment(PaymentId, SenderId, Amount) VALUES
(1, 1, 50.00),
(2, 1, 45.00),
(3, 2, 95.00),
(4, 2, 105.00);
クエリ
WITH
CTE_InvoiceIntervals
AS
(
SELECT
I.InvoiceId
,I.ReceiverId AS ClientID
,I.Priority
,SUM(I.Amount) OVER (PARTITION BY I.ReceiverId ORDER BY I.Priority
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS InvoiceInterval
FROM @Invoice AS I
)
,CTE_PaymentIntervals
AS
(
SELECT
P.PaymentId
,P.SenderId AS ClientID
,P.PaymentId AS Priority
,SUM(P.Amount) OVER (PARTITION BY P.SenderId ORDER BY P.PaymentID
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS PaymentInterval
FROM @Payment AS P
)
,CTE_AllIntervals
AS
(
SELECT
ClientID
,InvoiceInterval AS Interval
FROM CTE_InvoiceIntervals
UNION
SELECT
ClientID
,PaymentInterval AS Interval
FROM CTE_PaymentIntervals
)
SELECT *
FROM
CTE_AllIntervals
OUTER APPLY
(
SELECT TOP(1) CTE_InvoiceIntervals.InvoiceId
FROM CTE_InvoiceIntervals
WHERE
CTE_InvoiceIntervals.ClientID = CTE_AllIntervals.ClientID
AND CTE_InvoiceIntervals.InvoiceInterval >= CTE_AllIntervals.Interval
ORDER BY
CTE_InvoiceIntervals.InvoiceInterval
) AS A_Invoices
OUTER APPLY
(
SELECT TOP(1) CTE_PaymentIntervals.PaymentId
FROM CTE_PaymentIntervals
WHERE
CTE_PaymentIntervals.ClientID = CTE_AllIntervals.ClientID
AND CTE_PaymentIntervals.PaymentInterval >= CTE_AllIntervals.Interval
ORDER BY
CTE_PaymentIntervals.PaymentInterval
) AS A_Payments
ORDER BY
ClientID
,Interval;
結果
+----------+----------+-----------+-----------+
| ClientID | Interval | InvoiceId | PaymentId |
+----------+----------+-----------+-----------+
| 1 | 50.00 | 1 | 1 |
| 1 | 95.00 | 1 | 2 |
| 1 | 100.00 | 1 | NULL |
| 1 | 200.00 | 2 | NULL |
| 1 | 400.00 | 5 | NULL |
| 2 | 95.00 | 3 | 3 |
| 2 | 100.00 | 3 | 4 |
| 2 | 200.00 | 4 | 4 |
+----------+----------+-----------+-----------+
あなたは答えを待っている間、あなたは[これを熟読することをお勧めします](http:// stackoverflow。com/questions/9420173/sql-subtracting-a-depleting-from-rows/9421009#9421009)質問。 – HABO
SQL Server 2014を質問に追加します。 – Ize
サンプルデータを使用するだけで、期待した結果が得られますか? – jyao