0

我有一个事务表,它跟踪事务的所有细节,每个事务都可以有一个相关的事务。我在查询相关事务池中查找所有事务时遇到问题。

示例:2 个表:Transactions 和 RelatedTransactions

RelatedTransactions 有一个 TransactionID 和一个 RelatedTransactionID

假设我有 5 笔交易 1 与 2 相关 2 与 3 相关 3 与 4 相关 4 与 5 相关

交易 ID 相关交易 ID 1 2 2 3 3 4 4 5

我想要一个来自 RelatedTransaction 表的查询,如果提供 ID 1(或 2 或 3 或 4 或 5),它将返回 1、2、3、4、5

起初看起来很简单......我有一个问题

SELECT RelatedTransactionID FROM RelatedTransactions WHERE TransactionID = 1

当所有相关事务都有 1 作为父事务时,它显然有效。

因此,我添加的下一件事是获取 TransID 1 是相关交易的所有交易

我添加了

SELECT TransactionID WHERE RelatedTransactionID = 1

这一直有效,直到关系更深。

我从那里开始并添加了一个临时表来帮助我。

create table #RTS (TransactionID int );
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.RelatedTransactionID = @ID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM TransactionsRelated tr WHERE tr.TransactionID = @ID;
INSERT INTO #RTS SELECT @ID;
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.TransactionID IN (SELECT TransactionID FROM TransactionsRelated WHERE RelatedTransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.RelatedTransactionID IN (SELECT TransactionID FROM TransactionsRelated WHERE RelatedTransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.TransactionID IN (SELECT RelatedTransactionID FROM TransactionsRelated WHERE TransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.RelatedTransactionID IN (SELECT RelatedTransactionID FROM TransactionsRelated WHERE TransactionID = @ID);

如果我比那更深,我仍然没有得到一切。

因此,我采用了该 temptable 并添加了查询,以获取当前事务的所有相关事务。

INSERT INTO #RTS SELECT tr.TransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.RelatedTransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.TransactionID = rts.TransactionID;

当我意识到我仍然没有把它全部覆盖时,我又做了 3 次以确保我能处理好它们。我正在做的最后一个查询是

create table #RTS (TransactionID int );

INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.RelatedTransactionID = @ID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM TransactionsRelated tr WHERE tr.TransactionID = @ID;
INSERT INTO #RTS SELECT @ID;
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.TransactionID IN (SELECT TransactionID FROM TransactionsRelated WHERE RelatedTransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.RelatedTransactionID IN (SELECT TransactionID FROM TransactionsRelated WHERE RelatedTransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.TransactionID IN (SELECT RelatedTransactionID FROM TransactionsRelated WHERE TransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM TransactionsRelated tr WHERE tr.RelatedTransactionID IN (SELECT RelatedTransactionID FROM TransactionsRelated WHERE TransactionID = @ID);
INSERT INTO #RTS SELECT tr.TransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.RelatedTransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.TransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.TransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.RelatedTransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.TransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.TransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.RelatedTransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.TransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.TransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.RelatedTransactionID = rts.TransactionID;
INSERT INTO #RTS SELECT tr.RelatedTransactionID FROM #RTS rts INNER JOIN TransactionsRelated tr on tr.TransactionID = rts.TransactionID;

SELECT DISTINCT t.ID, t.CreateDate, t.TransactionDate, t.Amount, t.TypeID, t.SourceID, t.UserID, ts.Name as Source, tt.Name as TypeName, t.Subject 
FROM Transactions t INNER JOIN #RTS r on r.TransactionID = t.ID INNER JOIN TransactionSources ts on t.SourceID = ts.ID INNER JOIN TransactionTypes tt on tt.ID = t.TypeID ORDER BY TransactionDate DESC

DROP TABLE #RTS;

这是按原样工作的,但我假设如果事务有 20 多个级别的关系,它可能无法到达它们。

既然该产品是功能性的,我真正想知道的是是否有某种方式可以更好地在 SQL 中递归地执行此操作(如果重要,则为 MSSQL/Azure)。一定有更好的方法。

4

1 回答 1

0

我认为您需要的是递归查询。

在 SQL Server 2005 及更高版本中,您可以使用 Common Table Expressions 编写它

例如

WITH RecursiveTransactions AS

(

SELECT RelatedTransactionID, TransactionID FROM RelatedTransactions WHERE RelatedTransactionID IS NULL

UNION ALL

SELECT RelatedTransactionID, TransactionID FROM RelatedTransactions a JOIN RecursiveTransactions cte ON cte.TransactionID  = a.RelatedTransactionID

)

SELECT RelatedTransactionID, TransactionID FROM RecursiveTransactions 
WHERE TransactionID  = @ID

如果您的 DBMS 不支持 CTE,那么您可以编写一个递归 SP,它基本上将 @id 作为输入,并以相关 ID 作为 @id 调用自身

Example:

CREATE PROCEDURE RECURSIVETRANSACTIONID  AS
(@ID int)
BEGIN

IF #temp does not exists then
CREATE #temp
END IF


INSERT INTO #temp
SELECT RelatedTransactionID, TransactionID FROM RecursiveTransactions 
WHERE TransactionID  = @ID


IF(@id is not null) then -- this check makes sure it terminates when relation is not found (i.e. for last element)
EXEC RECURSIVETRANSACTIONID(SELECT RelatedTransactionID FROM #temp)


END
于 2013-09-13T20:46:00.820 回答