私は、IDへのすべての関連する行を照会するためのよりよい方法を思いつく方法について、(非常にゆっくりと)最後の2週間を把握しようとしています。私の会社は、ブランドの名前が変更され続けている状況にあり、交換されたブランドを指している以前のレコード(他のいくつかの表で)を変更するオプションはありません。SQL関連するすべての行を取得する
私がチェックするために人々を招待助けるために私のテーブルの小さな、小さなバージョンを作りました:
CREATE TABLE #GrwHist
(
ID INT
, Acronym VARCHAR(50)
, New_ID INT
)
INSERT INTO #GrwHist VALUES(1,'ABC',33)
INSERT INTO #GrwHist VALUES(21,'GST',NULL)
INSERT INTO #GrwHist VALUES(33,'MnY',48)
INSERT INTO #GrwHist VALUES(37,'FWR',89)
INSERT INTO #GrwHist VALUES(48,'DMZ',89)
INSERT INTO #GrwHist VALUES(89,'PLT',106)
INSERT INTO #GrwHist VALUES(106,'TnI',NULL)
INSERT INTO #GrwHist VALUES(120,'YIZ',143)
INSERT INTO #GrwHist VALUES(143,'INZ',NULL)
SELECT * FROM #GrwHist
/*
ID Acronym New_ID
--- ------- -------
1 ABC 33
21 GST NULL
33 MnY 48
37 FWR 89
48 DMZ 89
89 PLT 106
106 TnI NULL
120 YIZ 143
143 INZ NULL
*/
DECLARE @ID INT
SET @ID = 106
SELECT * FROM #GrwHist WHERE ID = @ID
UNION
SELECT * FROM #GrwHist WHERE New_ID in (@ID)
UNION
SELECT * FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (@ID))
UNION
SELECT * FROM #GrwHist WHERE New_ID in (
SELECT ID FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (@ID))
)
UNION
SELECT * FROM #GrwHist WHERE New_ID in (
SELECT ID FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (@ID)))
)
UNION
SELECT * FROM #GrwHist WHERE New_ID in (
SELECT ID FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (SELECT ID FROM #GrwHist WHERE New_ID in (@ID))))
) --And it grows and grows...
GO
DROP TABLE #GrwHist
最後のクエリがために、基本的である:
--If I need to get all IDs related to a given ID I will get the following results:
@ID = 106 --> 106, 89, 48, 37, 33, 1
@ID = 143 --> 143, 120
@ID = 21 --> 21
このクエリに問題があります7-8以上のレベルがあるかもしれないが、私はこれを動的に行うことができるのだろうかと思っていたので、リレーションが追加された別の行が追加されるたびにコードを変更する必要がないことを心配しない。 ID 106の新しい行を追加するために新しい行が追加された場合は、追加する必要があります。
with cte as (
select id, acronym, null as newid, id as baseid, 1 as lev,
cast(id as varchar(max)) as ids
from #GrwHist h
where newid is null
union all
select h.id, h.acronym, h.newid, cte.baseid, cte.lev + 1
cte.ids + ',' + cast(h.id as varchar(max)) as ids
from cte join
#GrwHist h
on h.new_id = cte.id
)
select baseid, ids
from (select cte.*, max(lev) over (partition by baseid) as maxlev
from cte
) cte
where maxlev = lev;
はEDIT::
重複がある場合は、あなたが使用して、それぞれのIDを取得することができます
は、あなたがマッチを得るために再帰CTEを使用することができます任意の助け
これは..驚くほどです。あなたにとってはシンプルだったようですが、私は理解し始めません。しかし、それはすべてのために働いています! ID 37の行は含まれていませんでした。 ID 37の行は、2つのブランドが結合されたケースです。それを追加する方法はありますか? @Busy。 – Busy
。 。それらが単純なチェーンでない場合、ロジックはもう少し複雑です。 –
2週間前にここで尋ねたいと思います。私は自分自身でそれを理解することがとても苦労していました。私は恐れていたので、誰かにちょうど私が試していないと教えて、スレッドを閉じるだけだったかもしれないからです。だから私は継続的な進歩なしに2週間ダイナミックSQLなどを試し続けました。どうもありがとうございます;答えが受け入れられました!あなたは神の御許です@GordonLinoff – Busy