2017-05-10 8 views
1

私は、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を使用することができます任意の助け

答えて

1

のために事前にありがとう:

select baseid, id 
from cte 
order by baseid; 

1つの行の値を取得するのは少し複雑です。

+0

これは..驚くほどです。あなたにとってはシンプルだったようですが、私は理解し始めません。しかし、それはすべてのために働いています! ID 37の行は含まれていませんでした。 ID 37の行は、2つのブランドが結合されたケースです。それを追加する方法はありますか? @Busy。 – Busy

+0

。 。それらが単純なチェーンでない場合、ロジックはもう少し複雑です。 –

+0

2週間前にここで尋ねたいと思います。私は自分自身でそれを理解することがとても苦労していました。私は恐れていたので、誰かにちょうど私が試していないと教えて、スレッドを閉じるだけだったかもしれないからです。だから私は継続的な進歩なしに2週間ダイナミックSQLなどを試し続けました。どうもありがとうございます;答えが受け入れられました!あなたは神の御許です@GordonLinoff – Busy

関連する問題