すべてのトランザクションが取り消されるトランザクションに ParentTransactionId を設定する新しいトランザクションによって取り消される場合、単純なLEFT JOIN
;を使用して行うことができます。
SELECT t1.* FROM Transactions t1
LEFT JOIN Transactions t2
ON t1.TransactionId = t2.ParentTransactionId
WHERE t2.TransactionId IS NULL;
t1
は、現在検討中のトランザクションでありt2
、キャンセルされる可能性のあるトランザクションです。キャンセルするトランザクションがない (つまりTransactionId
fort2
が存在しない) 場合は、行を返します。
私はあなたの最後の声明について確信が持てませんIf I cancelled the 3rd entry no records should return.
. テーブルに新しいトランザクションを追加せずに #3 をキャンセルするにはどうすればよいでしょうか? あなたが私たちに伝えていないキャンセルの条件が他にあるかもしれません...?
シンプルな SQLfiddle デモ。
編集: キャンセルされたトランザクション (またはキャンセル回数が奇数のトランザクション) が必要ないため、最後のトランザクションを表示するかどうかを判断するには、かなり複雑な再帰クエリが必要です。
WITH ChangeLog(TransactionID, Amount, ParentTransactionID,
IsCancel, OriginalTransactionID) AS
(
SELECT TransactionID, Amount, ParentTransactionID, 0, TransactionID
FROM Transactions WHERE ParentTransactionID IS NULL
UNION ALL
SELECT t.TransactionID, t.Amount, t.ParentTransactionID,
1-c.IsCancel, c.OriginalTransactionID
FROM Transactions t
JOIN ChangeLog c ON c.TransactionID = t.ParentTransactionID
)
SELECT c1.TransactionID, c1.Amount, c1.ParentTransactionID
FROM ChangeLog c1
LEFT JOIN ChangeLog c2
ON c1.TransactionID < c2.TransactionID
AND c1.OriginalTransactionID = c2.OriginalTransactionID
WHERE c2.TransactionID IS NULL AND c1.IsCancel=0
これは、3 つのトランザクションの例では、最後の行を表示しますが、最後の行がキャンセルされた場合、何も返されません。
SQLfiddle が再び起動したので、テストするフィドルを次に示します。
簡単な方法で行うのが少し難しい場合でも、クエリの簡単な説明が必要な場合があります。これは、一連の元のトランザクションから最後のトランザクションまでのキャンセルと元のトランザクション ID を追跡する再帰的な「ビュー」を定義しますChangeLog
(一連のトランザクションは、同じ OriginalTransactionId を持つすべてのトランザクションです)。その後、ChangeLog
自身と結合して最後のエントリ (つまり、キャンセルするトランザクションを持たないすべてのトランザクション) を見つけます。シリーズで見つかった最後のエントリがキャンセル ( IsCancel
=0) でない場合、それが表示されます。