我在一个表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 :(得分: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);