2017-01-16 46 views
1

我在一個表ProdHistory中有不同的產品序列號,其中包含表,如表所示,生產歷史。
例如,我有產品序列號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,但事實並非如此。

另一個問題是,如果我只是給出了上面的任何子部分,是否有可能返回相同的結果?

+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