找不到任何结果时找到下一个结果?

时间:2012-10-26 21:19:36

标签: sql sql-server common-table-expression

我试图用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

2 个答案:

答案 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)

SQL DEMO

注意:可以使用增量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 )