2014-03-05 46 views
0

我有一个PostgreSQL数据库,有两个表,我需要用它来做递归查询。
这两个表如下所示:PostgreSQL递归内部JOIN的CTE问题

Main table 
Box   pipeline plate solution 
---------------------------------------- 
X000001  Pipe  10000 75750 
X000001  Pipe  10000 75751 
X000001  Pipe  10001 75752 
X000001  Line  20000 75750 
Y000002  Pipe  10007 75800 
... 


Mixture (Solution History) 
made_solution_id  used_solution_id 
------------------------------------- 
75750    66746 
75750    73002 
66746    76380 
66746    80000 
... 

主要表格,你可以看到可以为每个板块多种解决方案,每个管道多板,以及每盒多条管线。制作混合物表格以便使用几种溶液来制备1种溶液(例如使用66746和73002来制备75750)。

我需要做的是为每一行在Mixture表上做一个递归查询,以便返回到整个开始的整个历史记录。

如从主表的第一行:

Box  pipeline plate made_solution_id  used_solution_id 
----------------------------------------------------------------- 
X000001 Pipe  10000 75750    66746 
X000001 Pipe  10000 75750    73002 
X000001 Pipe  10000 66746    76380 
X000001 Pipe  10000 66746    80000 

(一路递归直到有用于使溶液无父代) ......在主所有行做到这一点表

所以做这件事,我想出了这个递归查询:

WITH RECURSIVE parents (box, pipeline, plate, made_solution_id, used_solution_id) 
AS (
    --get leaf solution 
    SELECT 
    box, pipeline, plate, made_solution_id, used_solution_id 
    FROM 
    main 
    JOIN 
    mixture 
    ON 
    solution = made_solution_id 

UNION 
    --get parent solutions 
    SELECT 
    t.box, t.pipeline, t.plate, m.made_solution_id, m.used_solution_id 
    FROM 
    main t 
    JOIN 
    parents pt 
    ON 
    pt.made_solution_id = t.solution 
    JOIN 
    mixture m 
    ON 
    pt.used_solution_id = m.made_solution_id 
) 
SELECT * from parents 

然而,这没有奏效。这看起来像我的递归步骤不工作 - 查询会遍历主表中的所有行,但它只是返回主表和混合表之间JOIN的结果。

所以不是看上去就像上面的例子的结果,它看起来像这个:

Box  pipeline plate made_solution_id  used_solution_id 
----------------------------------------------------------------- 
X000001 Pipe  10000 75750    66746 
X000001 Pipe  10000 75750    73002 

我在做什么错?我阅读了递归查询文档,并在这里查看了递归CTE的几个问题,但我被卡住了。

编辑:改变的东西在SQL查询和小提琴的方式由欧文Brandstetter修改 http://www.sqlfiddle.com/#!11/9354f/4

PostgreSQL的8.4.17版本提供。

EDIT2:这是什么我的查询上的psql返回部分(注意:这只是一个例子,其中递归查询只是停止几个行后做递归事):

XYZ01 | High | 114043 |    49923 |    46573 
XYZ01 | High | 115424 |    49923 |    46573 
XYZ01 | High | 114043 |    46573 |    39853 
XYZ01 | High | 115424 |    46573 |    39853 
XYZ01 | High | 114043 |    46573 |    20456 
XYZ01 | High | 115424 |    46573 |    20456 
XYZ01 | High | 116694 |    49923 |    46573 
XYZ01 | High | 116691 |    49923 |    46573 
XYZ01 | High | 116697 |    49923 |    46573 
XYZ01 | High | 116693 |    49923 |    46573 
XYZ01 | High | 116696 |    49923 |    46573 
XYZ01 | High | 116699 |    49923 |    46573 
XYZ01 | High | 116698 |    49923 |    46573 
XYZ01 | High | 116692 |    49923 |    46573 
XYZ01 | High | 116695 |    49923 |    46573 

其中。 ..不是什么小提琴返回。

+0

我将使用递归cte遍历recursvie CTE中的混合表,然后将_that_的结果连接到主表。 –

+0

@a_horse_with_no_name我想过要做到这一点 - 但这是事情 - 对于可能使用的几个解决方案(以及它们各自的父解决方案)用于在主表中为每行创建解决方案,我将如何跟踪Box ,管道等信息,如果我这样做?我需要知道那些父母属于哪个盒子,管道和盘子(注意他们也可以在几个盒子里)。我没有看到一种方法来通过递归cte在混合表上进行,然后再加入到主表中。 – Joe

+1

我没有看到表格“盒子”(或任何适当的表格定义)的定义。另外:Postgres版本?理想情况下,你会为​​此提供一个SQL小提琴和一个测试用例。你可以在[这个存根]上建立(http://www.sqlfiddle.com/#!15/803b9)。 –

回答

1

您需要在CTE的第二部分返回m,不是t的框,管道,板。否则,你会通过解决方案,是的,但不会显示你目前的其他东西(这是你想要的)。您将仅显示第一个。

WITH RECURSIVE parents (box, pipeline, plate, made_solution_id, used_solution_id) 
AS (
    --get leaf solution 
    SELECT 
    box, pipeline, plate, made_solution_id, used_solution_id 
    FROM 
    main 
    JOIN 
    mixture 
    ON 
    solution = made_solution_id 

UNION 
    --get parent solutions 
    SELECT 
    m.box, m.pipeline, m.plate, m.made_solution_id, m.used_solution_id 
    FROM 
    main t 
    JOIN 
    parents pt 
    ON 
    pt.made_solution_id = t.solution 
    JOIN 
    mixture m 
    ON 
    pt.used_solution_id = m.made_solution_id 
) 
SELECT * from parents