2017-01-16 18 views
1

テーブル名には生産履歴が含まれているProdHistoryが1つのテーブル内に異なる製品シリアル番号を持っています。
たとえば、シリアルシリアル番号のある部品を使用する製品シリアルSER001があります。
我々はまた、これらの部品を生産するので、同じテーブルProdHistoryを使用してそのサブパーツを追跡します。
同じことがサブパーツと同じで、サブサブパーツがある場合は同じです。私は、私はすべての部品およびそれに関連するサブパーツシリアルを返すことができますどのようにちょうどメインのシリアル番号を、与えられてる場合同じテーブルからの再帰的クエリ

サンプルテーブル

IF OBJECT_ID('tempDB.dbo.#SAMPLETable') IS NOT NULL DROP TABLE #SAMPLETable 
CREATE TABLE #SAMPLETable 
(
    ITEMSEQ INT IDENTITY(1,1), 
    SERIAL NVARCHAR(10) COLLATE SQL_Latin1_General_CP850_CI_AS, 
    ITEMID NVARCHAR(10) COLLATE SQL_Latin1_General_CP850_CI_AS, 
    PARTSERIAL NVARCHAR(10) COLLATE SQL_Latin1_General_CP850_CI_AS, 
    PARTID NVARCHAR(10) COLLATE SQL_Latin1_General_CP850_CI_AS, 
    CREATEDDATETIME DATETIME 
) 

INSERT INTO 
     #SAMPLETable (SERIAL,ITEMID,PARTSERIAL,PARTID,CREATEDDATETIME) 
VALUES ('SER0001','ASY-1342','ITM0001','PRT-0808','2017-01-17'), 
     ('SER0001','ASY-1342','ITM0002','PRT-0809','2017-01-17'), 
     ('SER0001','ASY-1342','ITM0003','PRT-0810','2017-01-17'), 
     ('SER0001','ASY-1342','ITM0004','PRT-0811','2017-01-17'), 
     ('ITM0001','PRT-0808','UNT0001','PRT-2020','2017-01-16'), 
     ('ITM0002','PRT-0809','UNT0002','PRT-2021','2017-01-16'), 
     ('ITM0002','PRT-0809','UNT0003','PRT-2022','2017-01-16'), 
     ('ITM0003','PRT-0810','UNT0004','PRT-2023','2017-01-16'), 
     ('UNT0002','PRT-2021','DTA0000','PRT-1919','2017-01-15'), 
     ('UNT0003','PRT-2022','DTA0001','PRT-1818','2017-01-15'), 
     ('DTA0001','PRT-1818','LST0001','PRT-1717','2017-01-14') 

は質問は、ありますか?

サンプル結果:上記で

MainSerial SubSerial1 SubSerial2 SubSerial3 SubSerial4 
------------------------------------------------------- 
SER0001 ITM0001 UNT0001 
SER0001 ITM0002 UNT0002 DTA0000 
SER0001 ITM0002 UNT0003 DTA0001 LST0001 
SER0001 ITM0003 UNT0004 
SER0001 ITM0004 

、シリアル番号がありますどのように多くの部品やサブパーツ明確ではありません。
私が今行っていることは、それを一つずつ照会することなので、私は自分のコードを投稿しませんでした。
サブパートの数がわかっている場合は、入れ子にしてJoinsにすることはできますが、それはできません。

もう1つの質問は、私が上記のサブパートのいずれかを与えられただけで、同じ結果を返すことができるかどうかです。

+0

部分は4つのレベル以上のものを持ってもらえますか?もしそうなら、私はアプリケーションレベルで可視化を扱うことをお勧めします – JohnHC

+3

テーブル構造とサンプルデータを投稿してください。意味のあるクエリを提供することができます。 –

+0

関連するサブパートを探す必要がある部分/サブパネルのアンカークエリでフィルタ付きCTEを使用する必要があります –

答えて

1

私は方法は、このような動的SQLを使用することであると思う:

-- Variables to generate SQL query string dynamically 
declare @cols nvarchar(max) = '', @joins nvarchar(max) = '', @sql nvarchar(max) = '';  

-- Using CTE to iterate parent-child records 
with cte(i, cols, joins, itemId, serial, partId, partSerial) as (
    select 
     1, -- Level or depth of hierarchically tree 
     N's1.serial MainSerial, s1.partSerial SubSerial'+cast(1 as varchar(max)), 
     N'yourTable s'+cast(1 as varchar(max)), 
     s.itemId, s.serial, s.partId, s.partSerial 
    from yourTable s 
    -- A way to filter root-parents is filtering items those are not in parts 
    where s.itemId not in (select si.partId from yourTable si) 
    union all 
    select 
     i+1, 
     cols + N', s'+cast(i+1 as varchar(max))+N'.partSerial SubSerial'+cast(i+1 as varchar(max)), 
     joins + N' left join yourTable s'+cast(i+1 as varchar(max))+N' on s'+cast(i as varchar(max))+N'.partId = s'+cast(i+1 as varchar(max))+N'.itemId', 
     st.itemId, st.serial, st.partId, st.partSerial 
    from cte 
    join #sampleTable st on cte.partId = st.itemId 
) 
-- Now we need only strings of deepest level 
select top(1) 
    @cols = cols, @joins = joins 
from cte 
order by i desc; 

-- Finalize and executing query string 
set @sql = N'select ' + @cols + N' from ' + @joins + N' where s1.itemId not in (select s.partId from yourTable s)'; 
exec(@sql); 

追加注:生成されたクエリは次のとおりです。

select s1.serial MainSerial 
    , s1.partSerial SubSerial1 
    , s2.partSerial SubSerial2 
    , s3.partSerial SubSerial3 
    , s4.partSerial SubSerial4 
    --, ... 
from yourTable s1 
    left join yourTable s2 on s1.partId = s2.itemId 
    left join yourTable s3 on s2.partId = s3.itemId 
    left join yourTable s4 on s3.partId = s4.itemId 
--left join ... 
where s1.itemId not in (select s.partId from yourTable s); 
+0

これからたくさん学んだ。あなたは正しいです、私はSQL上で動的クエリを調べていません。これはサンプルテーブル上で特に効果的です。複数の主要なシリアル番号が動作するように自分のやり方で作業してください。乾杯。これは全く素晴らしい相手です。 – L42

関連する問題