如果所有事务都被新事务设置 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 再次启动,这里有一个要测试的小提琴。
即使以简单的方式有点难以做到,对查询的简短解释也可能是有序的;它定义了一个递归“视图”,ChangeLog
跟踪取消和原始事务 id 从原始到系列中的最后一个事务(一个系列是具有相同 OriginalTransactionId 的所有事务)。之后,它加入ChangeLog
自身以找到最后一个条目(即所有没有取消交易的交易)。如果在系列中找到的最后一个条目不是取消(IsCancel
=0),它将显示出来。