PostgreSQL里面有JOINs的递归CTE问题

时间:2014-03-05 17:50:15

标签: sql postgresql common-table-expression recursive-query

我有一个带有两个表的PostgreSQL数据库,我需要用它来进行递归查询 这两个表看起来像这样:

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)。

我需要做的是FOR EVERY ROW在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
然而,这不起作用。看起来我的递归步骤不起作用 - 查询DOES遍历Main表中的所有行,但它只返回Main表和Mixture表之间的JOIN结果。

所以不要像上面的示例结果那样,而是看起来像这样:

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

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

编辑:改变了Erwin Brandstetter提供的SQL Query和小提琴中的内容 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

哪个......不是小提琴的回归。

1 个答案:

答案 0 :(得分: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