我有一个带有两个表的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
哪个......不是小提琴的回归。
答案 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