我试图用CTE遍历一个层次结构,它在一个场景中工作正常而不是另一个场景,这就是我被困住的地方。
鉴于查询;
;WITH BOMcte (ID, Code, BomName , ProductID, ProductCode, ProductName , ParentAssemblyID )
AS
(
SELECT b.id,
b.code,
b.name,
p.id,
p.default_code,
p.name_template,
b.bom_id
FROM mrp_bom AS b
INNER JOIN product_product p on b .product_id = p.id
WHERE b. bom_id IS NULL
and b.id = @AssemblyID
UNION ALL
SELECT b.id,
b.code,
b.name,
p.id,
p.default_code,
p.name_template,
b.bom_id
FROM mrp_bom AS b
INNER JOIN product_product p on b .product_id = p.ID
INNER JOIN BOMcte AS cte ON b.bom_id = cte.ID
)
SELECT BoM.* FROM BOMcte BoM
查询的工作方式正如我预期的那样,因为BoM向下钻取bom_id列上的子boms。
在未找到子BoM的代码(来自OpenERP)中,(无bom_id)根据product_id搜索子产品:
sids = bom_obj.search(cr, uid, [('bom_id','=',False),('product_id','=',bom.product_id.id)])
我想知道是否有一种方法可以用来在SQL中完成同样的事情。一旦CTE没有返回行,请检查product_id和null bom_id。我曾想过另一个递归成员,但我认为这不是我想要的。
我知道我的问题可能不是很清楚但是,有什么建议吗?
这里的SQL小提琴示例数据:http://sqlfiddle.com/#!3/b9052/1
答案 0 :(得分:1)
尝试将以下内容作为HABO建议on b.bom_id = cte.ID or ( b.bom_id is NULL and b.product_id = cte.product_id )
并且您已经尝试过的原因不起作用的原因是它从未在逻辑上终止。
但是你确实有一个终止表达式,当没有找到孩子时,它会做一次。最简单的方法是添加一个UNION,它会检查以确保BOMcte中的行没有子项
WHERE NOT EXISTS (SELECT * FROM BOMcte bc WHERE b.id = bc.PARENTASSEMBLYID)
完整SQL
;WITH BOMcte (ID, Code, BomName , ProductID, ProductCode, ProductName , ParentAssemblyID )
AS
(
SELECT b.id,
b.code,
b.name,
p.id,
p.default_code,
p.name_template,
b.bom_id
FROM mrp_bom AS b
INNER JOIN product_product p on b .product_id = p.id
WHERE b. bom_id IS NULL
and b.id = @AssemblyID
UNION ALL
SELECT b.id,
b.code,
b.name,
p.id,
p.default_code,
p.name_template,
b.bom_id
FROM mrp_bom AS b
INNER JOIN product_product p on b .product_id = p.ID
INNER JOIN BOMcte AS cte ON b.bom_id = cte.ID
)
SELECT * FROM BOMcte
UNION
SELECT b.id,
b.code,
b.name,
p.id,
p.default_code,
p.name_template,
b.bom_id
FROM mrp_bom AS b
INNER JOIN product_product p on b.product_id = p.id
WHERE NOT EXISTS (SELECT * FROM BOMcte bc WHERE b.id = bc.PARENTASSEMBLYID)
注意:可以使用增量LEVEL值对CTE中的终止表达式进行编码,如递归查询中的MSDN article中所示的值
答案 1 :(得分:0)
我对你要做的事情有点不清楚,但你最后加入的事情可能会这样:
on b.bom_id = cte.ID or ( b.bom_id is NULL and b.product_id = cte.product_id )