嗨,这是从另一篇文章继续的,
SQL Recursive CTE 'where-used' / BOM explosion
最初的要求已得到解答,但我意识到我现在还有另一个最终要求。我在“1”之后拥有的数据(即描述等)希望对每个级别重复,以便描述正确地识别正确的父项。我尝试在最终选择中再次添加列,但它只是重复了级别 1 中的项目。如何做到这一点?
* 更新 * 我真的很难让测试数据/查询看起来像我想要的那样。我想让这些项目通过 bomid 相互关联。输出看起来像 img。
BOM和BOMVERSION之间的关系是一个项目在BOM表中有多个BOMID,每个bomID在BOMVERSION中都有对应的记录,通过BOMID您可以从BOMVERSION中获得不同的ITEMID。该 itemID 本身可以存在于具有多个 BOMID 的 BOM 表中。我知道这很令人困惑,并且很难用测试数据来证明。这就是为什么我很高兴获得赏金。
*更新*根据我所了解到的,我已经重做了查询/测试数据。我无法让它完全执行我想要的操作,因此可能需要调整或添加查询/数据。我会输出我所期望的。基本上,当 BOM.ItemID 通过 BOMID 链接到 BV.ItemID 时,我希望 BV.ItemID 移动到下一个级别,然后如果该 BOM.ItemID 链接到另一个 BV.ItemID 则将该项目移动到下一个级别等等。以及与关卡中的项目相关的所有其他信息。
IF OBJECT_ID('tempdb..#BOM') IS NOT NULL
DROP TABLE #BOM;
CREATE TABLE #BOM
(
ItemID NVARCHAR(10) ,
BOMID NVARCHAR(10) ,
BOMQTY INT ,
UnitID NVARCHAR(10) ,
BOMQTYSERIE INT
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100001' , -- ItemID - nvarchar(10)
N'1A' , -- BOMID - nvarchar(10)
10 , -- BOMQTY - int
N'g' , -- UnitID - nvarchar(10)
5 -- Bomqtyserie - int
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100001' , -- ItemID - nvarchar(10)
N'2A' , -- BOMID - nvarchar(10)
15 , -- BOMQTY - int
N'kg' , -- UnitID - nvarchar(10)
13 -- Bomqtyserie - int
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100001' , -- ItemID - nvarchar(10)
N'3A' , -- BOMID - nvarchar(10)
16 , -- BOMQTY - int
N'l' , -- UnitID - nvarchar(10)
16 -- Bomqtyserie - int
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100002' , -- ItemID - nvarchar(10)
N'1A' , -- BOMID - nvarchar(10)
18 , -- BOMQTY - int
N'g' , -- UnitID - nvarchar(10)
17 -- Bomqtyserie - int
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100004' , -- ItemID - nvarchar(10)
N'2A' , -- BOMID - nvarchar(10)
20 , -- BOMQTY - int
N'kg' , -- UnitID - nvarchar(10)
11 -- Bomqtyserie - int
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100002' , -- ItemID - nvarchar(10)
N'2A' , -- BOMID - nvarchar(10)
23 , -- BOMQTY - int
N'kg' , -- UnitID - nvarchar(10)
19 -- Bomqtyserie - int
);
INSERT INTO #BOM
( ItemID ,
BOMID ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
)
VALUES ( N'100003' , -- ItemID - nvarchar(10)
N'2A' , -- BOMID - nvarchar(10)
25 , -- BOMQTY - int
N'kg' , -- UnitID - nvarchar(10)
21 -- Bomqtyserie - int
);
IF OBJECT_ID('tempdb..#BOMVERSION') IS NOT NULL
DROP TABLE #BOMVERSION;
CREATE TABLE #BOMVERSION
(
ItemID NVARCHAR(10) ,
BOMID NVARCHAR(10) ,
Name NVARCHAR(20) ,
Active BIT
);
INSERT INTO #BOMVERSION
( ItemID ,
BOMID ,
Name ,
Active
)
VALUES ( N'100002' , -- ItemID - nvarchar(10)
N'1A' , -- BOMID - nvarchar(10)
N'100002 Version' , -- Name - nvarchar(10)
1 -- Active - bit
);
INSERT INTO #BOMVERSION
( ItemID ,
BOMID ,
Name ,
Active
)
VALUES ( N'100002' , -- ItemID - nvarchar(10)
N'2A' , -- BOMID - nvarchar(10)
N'100002.1 Version' , -- Name - nvarchar(10)
1 -- Active - bit
);
INSERT INTO #BOMVERSION
( ItemID ,
BOMID ,
Name ,
Active
)
VALUES ( N'100003' , -- ItemID - nvarchar(10)
N'3A' , -- BOMID - nvarchar(10)
N'100003 Version' , -- Name - nvarchar(10)
1 -- Active - bit
);
INSERT INTO #BOMVERSION
( ItemID ,
BOMID ,
Name ,
Active
)
VALUES ( N'100004' , -- ItemID - nvarchar(10)
N'4A' , -- BOMID - nvarchar(10)
N'100004 Version' , -- Name - nvarchar(10)
1 -- Active - bit
);
INSERT INTO #BOMVERSION
( ItemID ,
BOMID ,
Name ,
Active
)
VALUES ( N'100005' , -- ItemID - nvarchar(10)
N'5A' , -- BOMID - nvarchar(10)
N'100005 Version' , -- Name - nvarchar(10)
1 -- Active - bit
);
IF OBJECT_ID('tempdb..#INVENTTABLE') IS NOT NULL
DROP TABLE #INVENTTABLE;
CREATE TABLE #INVENTTABLE
(
ItemID NVARCHAR(10) ,
Name NVARCHAR(20) ,
Product INT
);
INSERT INTO #INVENTTABLE
( ItemID, Name, Product )
VALUES ( N'100001', -- ItemID - nvarchar(10)
N'100001 Name', -- Name - nvarchar(10)
1 -- Product - int
);
INSERT INTO #INVENTTABLE
( ItemID, Name, Product )
VALUES ( N'100002', -- ItemID - nvarchar(10)
N'100002 Name', -- Name - nvarchar(10)
2 -- Product - int
);
INSERT INTO #INVENTTABLE
( ItemID, Name, Product )
VALUES ( N'100003', -- ItemID - nvarchar(10)
N'100003 Name', -- Name - nvarchar(10)
3 -- Product - int
);
INSERT INTO #INVENTTABLE
( ItemID, Name, Product )
VALUES ( N'100004', -- ItemID - nvarchar(10)
N'100004 Name', -- Name - nvarchar(10)
4 -- Product - int
);
INSERT INTO #INVENTTABLE
( ItemID, Name, Product )
VALUES ( N'100005', -- ItemID - nvarchar(10)
N'100005 Name', -- Name - nvarchar(10)
5 -- Product - int
);
IF OBJECT_ID('tempdb..#ECORESPRODUCTTRANSLATION') IS NOT NULL
DROP TABLE #ECORESPRODUCTTRANSLATION;
CREATE TABLE #ECORESPRODUCTTRANSLATION
(
Product INT ,
Name NVARCHAR(20)
);
INSERT INTO #ECORESPRODUCTTRANSLATION
( Product, Name )
VALUES ( 1, -- Product - int
N'100001 Description' -- Name - nvarchar(10)
);
INSERT INTO #ECORESPRODUCTTRANSLATION
( Product, Name )
VALUES ( 2, -- Product - int
N'100002 Description' -- Name - nvarchar(10)
);
INSERT INTO #ECORESPRODUCTTRANSLATION
( Product, Name )
VALUES ( 3, -- Product - int
N'100003 Description' -- Name - nvarchar(10)
);
INSERT INTO #ECORESPRODUCTTRANSLATION
( Product, Name )
VALUES ( 4, -- Product - int
N'100004 Description' -- Name - nvarchar(10)
);
INSERT INTO #ECORESPRODUCTTRANSLATION
( Product, Name )
VALUES ( 5, -- Product - int
N'100005 Description' -- Name - nvarchar(10)
);
WITH CTE
AS ( SELECT B.ItemID AS MainItem ,
BV.Name AS BVName ,
B.BOMID ,
BV.ItemID AS ParentItem ,
ECPT.Name AS ParentItemName ,
B.BOMQTY ,
B.UnitID ,
B.BOMQTYSERIE ,
1 AS [Level]
FROM #BOM AS B
JOIN #BOMVERSION AS BV ON BV.BOMID = B.BOMID
JOIN #INVENTTABLE AS IT ON IT.ItemID = BV.ItemID
JOIN #ECORESPRODUCTTRANSLATION AS ECPT ON ECPT.Product = IT.Product
WHERE B.ItemID = '100001'
AND BV.Active = 1
UNION ALL
SELECT C.MainItem ,
C.BVName ,
C.BOMID ,
BV.ItemID ,
C.ParentItemName ,
C.BOMQTY ,
C.UnitID ,
C.BOMQTYSERIE ,
C.[Level] + 1
FROM CTE AS C
JOIN #BOM AS B ON C.ParentItem = B.ItemID
JOIN #BOMVERSION AS BV ON BV.BOMID = B.BOMID
WHERE C.[Level] <= 7
)
SELECT MainItem ,
[1] AS Level1 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE ,
[2] AS Level2 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE ,
[3] AS Level3 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE ,
[4] AS Level4 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE ,
[5] AS Level5 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE ,
[6] AS Level6 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE ,
[7] AS Level7 ,
BVName ,
ParentItemName ,
BOMQTY ,
UnitID ,
BOMQTYSERIE
FROM CTE PIVOT ( MAX(ParentItem) FOR [Level] IN ( [1], [2], [3], [4],
[5], [6], [7] ) ) AS pvt;
最佳答案
这是一个易于理解和维护的版本:
;
WITH CTE
AS ( SELECT B.RECID AS MainID ,
B.ITEMID AS MainItem ,
BV.NAME ,
BV.ITEMID AS ParentItem ,
ECPT.NAME AS ParentItemName ,
B.BOMQTY ,
B.UNITID ,
B.BOMQTYSERIE ,
0 AS [level]
FROM #BOM B
JOIN #BOMVERSION BV ON BV.BOMID = B.BOMID
JOIN #INVENTTABLE AS IT ON IT.ITEMID = BV.ITEMID
JOIN #ECORESPRODUCTTRANSLATION AS ECPT ON ECPT.PRODUCT = IT.PRODUCT
WHERE B.ITEMID = '113621'
AND BV.ACTIVE = '1'
UNION ALL
SELECT C.MainID ,
C.MainItem ,
C.NAME ,
BV.ITEMID ,
C.ParentItemName ,
C.BOMQTY ,
C.UNITID ,
C.BOMQTYSERIE ,
C.[level] + 1
FROM CTE C
JOIN #BOM B ON C.ParentItem = B.ITEMID
JOIN #BOMVERSION BV ON BV.BOMID = B.BOMID
WHERE C.[level] <= 6
)
SELECT B.ITEMID ,
C1.ParentItem AS ParentItem1 ,
C1.NAME AS BVName1 ,
C1.ParentItemName AS ParentItemName1 ,
C1.BOMQTY AS BomQty1 ,
C1.UNITID AS UnitID1 ,
C1.BOMQTYSERIE AS BomQtySerie1 ,
C2.ParentItem AS ParentItem2 ,
C2.NAME AS BVName2 ,
C2.ParentItemName AS ParentItemName2 ,
C2.BOMQTY AS BomQty2 ,
C2.UNITID AS UnitID2 ,
C2.BOMQTYSERIE AS BomQtySerie2 ,
C3.ParentItem AS ParentItem3 ,
C3.NAME AS BVName3 ,
C3.ParentItemName AS ParentItemName3 ,
C3.BOMQTY AS BomQty3 ,
C3.UNITID AS UnitID3 ,
C3.BOMQTYSERIE AS BomQtySerie3 ,
C4.ParentItem AS ParentItem2 ,
C4.NAME AS BVName2 ,
C4.ParentItemName AS ParentItemName4 ,
C4.BOMQTY AS BomQty4 ,
C4.UNITID AS UnitID4 ,
C4.BOMQTYSERIE AS BomQtySerie4 ,
C5.ParentItem AS ParentItem5 ,
C5.NAME AS BVName5 ,
C5.ParentItemName AS ParentItemName5 ,
C5.BOMQTY AS BomQty5 ,
C5.UNITID AS UnitID5 ,
C5.BOMQTYSERIE AS BomQtySerie5 ,
C6.ParentItem AS ParentItem6 ,
C6.NAME AS BVName6 ,
C6.ParentItemName AS ParentItemName6 ,
C6.BOMQTY AS BomQty6 ,
C6.UNITID AS UnitID6 ,
C6.BOMQTYSERIE AS BomQtySerie6 ,
C7.ParentItem AS ParentItem7 ,
C7.NAME AS BVName7 ,
C7.ParentItemName AS ParentItemName7 ,
C7.BOMQTY AS BomQty7 ,
C7.UNITID AS UnitID7 ,
C7.BOMQTYSERIE AS BomQtySerie7
FROM #BOM B
LEFT JOIN CTE C1 ON B.RECID = C1.MainID
AND C1.[level] = 0
LEFT JOIN CTE C2 ON B.RECID = C2.MainID
AND C2.[level] = 1
LEFT JOIN CTE C3 ON B.RECID = C3.MainID
AND C3.[level] = 2
LEFT JOIN CTE C4 ON B.RECID = C4.MainID
AND C4.[level] = 3
LEFT JOIN CTE C5 ON B.RECID = C5.MainID
AND C5.[level] = 4
LEFT JOIN CTE C6 ON B.RECID = C6.MainID
AND C6.[level] = 5
LEFT JOIN CTE C7 ON B.RECID = C7.MainID
AND C7.[level] = 6
WHERE B.ITEMID = '113621'
AND C1.ParentItem IS NOT NULL;
编辑:
输入:
INSERT INTO #BOM VALUES
( 1, N'10', N'1A' ),
( 2, N'20', N'2A' ),
( 3, N'30', N'3A' ),
( 4, N'40', N'4A' ),
( 5, N'50', N'5A' ),
( 6, N'60', N'6A' ),
( 7, N'70', N'7A' ),
( 8, N'80', N'8A' ),
( 9, N'90', N'9A' ),
( 10, N'100', N'10A' ),
( 11, N'110', N'11A' )
INSERT INTO #BOMVERSION VALUES
( 1, N'20', N'10 PRE', N'1A' ),
( 2, N'30', N'20 PRE', N'2A' ),
( 3, N'40', N'30 PRE', N'3A' ),
( 4, N'50', N'40 PRE', N'4A' ),
( 5, N'60', N'50 PRE', N'5A' ),
( 6, N'70', N'60 PRE', N'6A' ),
( 7, N'80', N'70 PRE', N'7A' ),
( 8, N'100', N'90 PRE', N'9A' ),
( 9, N'110', N'100 PRE', N'10A' ),
( 9, N'120', N'110 PRE', N'11A' )
INSERT INTO #Item VALUES
( 1, N'10', N'10 DESC' ),
( 2, N'20', N'20 DESC' ),
( 3, N'30', N'30 DESC' ),
( 4, N'40', N'40 DESC' ),
( 5, N'50', N'50 DESC' ),
( 6, N'60', N'60 DESC' ),
( 7, N'70', N'70 DESC' ),
( 8, N'80', N'80 DESC' ),
( 9, N'90', N'90 DESC' ),
( 10, N'100', N'100 DESC' ),
( 11, N'110', N'110 DESC' )
输出:
关于SQL 递归 CTE 'where-used'/BOM 爆炸第 2 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30259328/