皆さんありがとうございます。色々試してみましてなんとかなりそうです。
振り返りも含めて記載していますので、もし何か問題や簡単にできそうな点があればご指摘いただけますと幸いです。
日付は見にくいのでH:mm:ssを省いていますが実際には入っています。
テーブル名:PurchaseTable
ID | Quantity | Date
001 1 2023/1/1
001 1 2023/1/2
001 2 2023/1/2
002 2 2023/1/2
002 1 2023/1/3
テーブル名:ReturnTable
ID | Quantity| Date
001 1 2023/1/3
001 2 2023/1/4
002 2 2023/1/4
①ReturnTableにRow_NumberでId,数量ごとに日付昇順に番号を割り振りました。
ROW_NUMBER() OVER(PARTITION BY p.Id, r.Quantity ORDER BY rDate) AS RowNumber
イメージ
ID | Quantity | rDate | RowNumber
001 1 2023/1/3 1
001 2 2023/1/4 1
002 2 2023/1/4 1
②テンポラリーテーブルとして、下記のようにPurchaseDate <= ReturnDateという条件のもと日付降順に採番し、PurchaseTableを整形しました。これで返品対象となりうる購入レコードを抽出します。
WITH CTE AS (
SELECT
p.Id,
p.Quantity,
p.pDate,
ROW_NUMBER() OVER(PARTITION BY p.Id, p.Quantity ORDER BY pDate DESC) AS RowNumber
FROM
PurchaseTable p
WHERE EXISTS (SELECT 1 FROM ReturnTable r WHERE p.pDate <= r.rDate)
)
SELECT * FROM CTE を行うと下記のような結果になりました。
ID | Quantity | pDate | RowNumber
001 1 2023/1/2 1
001 1 2023/1/1 2
001 2 2023/1/3 1
002 2 2023/1/3 1
002 1 2023/1/2 1
③最後にこれらのテーブルを結合しました。日付の条件、数量の条件、新たに追加した採番番号が一致するという条件のもとこれらを結合すると、採番番号が一致しているデータは返品できたということになります。
SELECT p.Id, p.Quantity, p.pDate, r.rDate, CTE.RowNumber, r.RowNumber FROM CTE
INNER JOIN ReturnTable r ON CTE.Id = r.ID AND CTE.Quantity = ABS(r.Quantity) AND CTE.RowNumber = r.RowNumber
RIGHT JOIN PurchaseTable p ON CTE.Id = p.ID AND CTE.Quantity = p.Quantity AND CTE.pDate = p.pDate
結果
ID | Quantity | pDate | rDate | CTE.RowNumber | r.RowNumber
001 1 (2023/1/1) NULL NULL NULL
001 1 (2023/1/2) (2023/1/3) 1 1
001 2 (2023/1/3) (2023/1/4) 1 1
002 2 (2023/1/2) (2023/1/4) 1 1
002 1 (2023/1/3) NULL NULL NULL
私が検証用に簡易的に作成したローカル環境では上手くいったのですが、テスト環境ではまだエラーがでるため何か問題があるかもしれませんが、問題のロジックは解決しているように見えました。
何か問題、ご指摘あればぜひお願いいたします。