【问题标题】:one to one parent child relationship sql server一对一父子关系sql server
【发布时间】:2012-10-26 10:13:47
【问题描述】:

我有一个表格,其中包含 TransactionIDAmountParentTransactionID 字段 可以取消交易,因此使用amountParentTransactionID 发布的新条目被取消TransactionID

让我们说一个交易

1100 空值

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

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))

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

【问题讨论】:

    标签: sql-server parent-child


    【解决方案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 是可能取消的事务。如果没有取消事务(即t2TransactionId 不存在),则返回该行。

    不过,我不确定你最后的声明,If I cancelled the 3rd entry no records should return.。如果不向表中添加新事务,您将如何取消 #3?您可能还有其他一些您没有告诉我们的取消条件...?

    Simple SQLfiddle demo.

    编辑:由于您不想要取消的交易(或者更确切地说是取消次数为奇数的交易),您需要一个相当复杂的递归查询来确定是否显示最后一笔交易;

    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 再次启动,here is a fiddle to test with

    查询的简短解释可能是有序的,即使以简单的方式有点难以做到;它定义了一个递归“视图”ChangeLog,它跟踪取消和原始事务 id 从原始事务到系列中的最后一个事务(一个系列是具有相同 OriginalTransactionId 的所有事务)。之后,它将ChangeLog 与自身连接以查找最后一个条目(即所有没有取消交易的交易)。如果在系列中找到的最后一个条目不是取消 (IsCancel=0),它将显示出来。

    【讨论】:

    • 谢谢,如果我取消了第三笔交易,将会使用 TransactionID : 4 Amount : -100 ParentTransactionID : 3 上面的查询结果是最后一个条目。在这种情况下,不应有任何行在所有交易被取消时返回。
    • @user1204716 那么我怎么知道它被取消了呢?这是第一笔交易的相反金额,还是您在考虑其他方式?
    • 如果一个交易被取消,那么一个新的条目就会被创建。新事务的parenttransactionid就是被取消事务的transactionid。
    • @user1204716 我想要的是;为什么您现有的示例会返回第三个条目(原始交易在两种情况下都已被取消),而额外的取消会导致返回 no 条目?还是我完全误解了什么?
    • 我不想显示已取消的交易。我做了一笔交易(1),我取消了它(2)。所以我不想显示这两项交易。如果我再次取消了交易(2)(Cancelled Transaction),我需要显示新的交易(3)(Cancelled Cancelled)。然后只有它与总数匹配。如果我取消第 3 次,则进行第 4 次交易,因此无需显示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    相关资源
    最近更新 更多