私はいくつかのデータ、実際の例を持っています。データを特定の方法で表示するために、必要な結果を得るためにデータを操作しなければならないような方法でデータが保存されます。基本的に、請求書には 2 つの異なるタイプがあります。注文が処理される前に金額が請求される事前請求書 (P)。出荷後に残金が請求される標準請求書 (I)。通常の状況下では、標準請求書から請求書前の金額が差し引かれると予想されます。たとえば、請求前請求書が 2 ドルで注文が 10 ドルの場合、標準請求書は 8 ドルになります。ただし、標準の請求書は $10 として保存されます。
以下は完全に操作可能なクエリです (そのクエリは操作可能です! これは罠です!) データを入力し、必要な結果を返します。目標は、請求額を取得し、それが事前請求書の場合はその金額を返すことです。ただし、それが標準の請求書の場合は、事前請求書の値を「使い果たし」、新しい金額、最小ゼロを返します。事前請求書は任意の金額になる可能性があり、技術的にはいつでも必要になる可能性があるため、6 つのシナリオを含めました。
これに関するご支援をいただければ幸いです。UNBOUNDED PRECEDING タイプのものを含むいくつかのウィンドウ関数を試しましたが、再帰的で無限ループに入る必要があるように常に思えました。したがって、以下の私のブルートフォースアプローチ。
DECLARE @PData TABLE (
CustNum INT
,TransNum INT
,InvType NVARCHAR(1)
,InvAmt DECIMAL(5,2)
,CRank INT
,TRank INT
,ModInvAmt DECIMAL(5,2)
)
INSERT INTO @PData (
CustNum
,TransNum
,InvType
,InvAmt
)
VALUES
(124, 1,'P',2)
,(124, 2,'I',10)
,(124, 3,'I',10)
,(153, 4,'I',10)
,(153, 5,'P',2)
,(153, 6,'I',10)
,(324, 7,'I',10)
,(324, 8,'I',10)
,(324, 9,'P',2)
,(441,10,'P',12)
,(441,11,'I',10)
,(441,12,'I',10)
,(455,13,'I',10)
,(455,14,'P',12)
,(455,15,'I',10)
,(667,16,'I',10)
,(667,17,'I',10)
,(667,18,'P',12)
UPDATE pd1
SET CRank = pd2.CDR
FROM @PData pd1
JOIN (SELECT CustNum, TransNum, DENSE_RANK() OVER (ORDER BY CustNum) AS CDR
FROM @PData) pd2
ON pd1.TransNum = pd2.TransNum
UPDATE pd1
SET TRank = pd2.TDR
FROM @PData pd1
JOIN (SELECT CustNum, TransNum, DENSE_RANK() OVER (PARTITION BY CustNum ORDER BY TransNum) AS TDR
FROM @PData) pd2
ON pd1.TransNum = pd2.TransNum
DECLARE @Counter1 INT
,@Counter2 INT
,@CBal DECIMAL(5,2)
,@TNum INT
,@IAmt DECIMAL(5,2)
SET @Counter1 = 0
WHILE @Counter1 < (SELECT MAX(CRank) FROM @PData)
BEGIN
SET @Counter1 += 1
SET @CBal = 0
SET @Counter2 = 0
WHILE @Counter2 < (SELECT MAX(TRank) FROM @PData WHERE CRank = @Counter1)
BEGIN
SET @Counter2 += 1
SET @TNum = (SELECT TransNum FROM @PData WHERE CRank = @Counter1 AND TRank = @Counter2)
SET @IAmt = (SELECT InvAmt FROM @PData WHERE TransNum = @TNum)
IF (SELECT InvType FROM @PData WHERE TransNum = @TNum) = 'P'
BEGIN
UPDATE @PData SET ModInvAmt = @IAmt WHERE TransNum = @TNum
SET @CBal += -@IAmt
END
ELSE
BEGIN
UPDATE @PData SET ModInvAmt = (ABS(@IAmt+@CBal)+(@IAmt+@CBal))/2 -- MINIMUM = 0
WHERE TransNum = @TNum
SET @CBal += (@IAmt - (ABS(@IAmt+@CBal)+(@IAmt+@CBal))/2)
END
END
END
SELECT CustNum
,TransNum
,InvType
,InvAmt
,ModInvAmt
FROM @PData
通常、元の請求書の金額は報告しませんが、新しい請求書の金額だけを報告しますが、どのように変化したかがより明確になるように、ここに記載しました。
CustNum TransNum InvType InvAmt ModInvAmt
124 1 P 2.00 2.00
124 2 I 10.00 8.00
124 3 I 10.00 10.00
153 4 I 10.00 10.00
153 5 P 2.00 2.00
153 6 I 10.00 8.00
324 7 I 10.00 10.00
324 8 I 10.00 10.00
324 9 P 2.00 2.00
441 10 P 12.00 12.00
441 11 I 10.00 0.00
441 12 I 10.00 8.00
455 13 I 10.00 10.00
455 14 P 12.00 12.00
455 15 I 10.00 0.00
667 16 I 10.00 10.00
667 17 I 10.00 10.00
667 18 P 12.00 12.00