父/子SQL查询 - 获取所有父和子

时间:2013-09-13 20:23:26

标签: sql sql-server

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

实施例: 2表:交易和相关交易

RelatedTransactions有一个TransactionID和一个RelatedTransactionID

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

TransactionID RelatedTransactionID 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)。必须有更好的方法。

1 个答案:

答案 0 :(得分:0)

我认为你需要的是一个递归查询。

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

编写它

E.g。

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作为输入并使用relatedID调用自身为@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