1

我有一个带有字段的表TransactionIDAmount并且ParentTransactionID 可以取消交易,因此可以取消发布新条目amountParentTransactionID取消TransactionID

让我们说一笔交易

1 100 空

我取消了上面的条目,它会喜欢

2 -100 1

再次取消了上述交易,所以它应该喜欢

3 100 2

当我获取时,我应该得到记录 3,因为 ID 1 和 2 被取消了。结果应该是

3 100 2

如果我取消了第三个条目,则不应返回任何记录。

SELECT * FROM Transaction t
WHERE NOT EXISTS (SELECT TOP 1 NULL FROM Transaction pt
WHERE (pt.ParentTransactionID = t.TransactionID OR t.ParentTransactionID = pt.TransactionID)
AND ABS(t.Amount) = ABS(pt.Amount))

如果仅进行一级取消,则此方法有效。

4

1 回答 1

1

如果所有事务都被新事务设置 ParentTransactionId 取消,则可以使用简单的LEFT JOIN;

SELECT t1.* FROM Transactions t1
LEFT JOIN Transactions t2
  ON t1.TransactionId = t2.ParentTransactionId
WHERE t2.TransactionId IS NULL;

t1是我们当前正在查看的交易并且t2是可能取消的交易。如果没有取消事务(即TransactionIdfort2不存在),则返回该行。

不过,我不确定您的最后陈述,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),它将显示出来。

于 2012-10-26T10:24:42.217 回答