我最近在postgreSQL中要求recursive query。答案很合适,但只要我添加一个JOIN元素,它就会给我以下错误:
错误:缺少表“n”的FROM子句条目:WITH RECURSIVE链 AS(SELECT n.pordnr,pz.pordnrzu,n.abschl,n.stg,n.kzfa,n.pversion FROM pord n LEFT JOIN pordnrzu pz ON pz.pordnr = n.pordnr WHERE n.pordnr = 112 UNION ALL SELECT n.pordnr,pz2.pordnrzu,n.abschl, n.stg,n.kzfa,n.pversion FROM chain c LEFT JOIN pordnrzu pz2 ON pz2.pordnr = n.pordnr INNER JOIN pord n ON(c.pordnrzu = n.pordnr) WHERE c.abschl IS NULL)SELECT * FROM chain c WHERE c.abschl IS NOT NULL
我尝试了几次修改,但我无法让它工作。我想要的是,pordnrzu
正在实施以寻找另一个pordnr
。
所以:pordnr
- > pordnrzu
- > pordnr
有什么我错过的吗?
这是样本表:
CREATE TABLE pord (
pordnr integer primary key,
abschl text,
stg text,
kzfa text,
pversion text
);
INSERT INTO pord (pordnr, abschl, stg, kzfa, pversion)
VALUES
(112, NULL, NULL, NULL, NULL),
(140, NULL, NULL, NULL, NULL),
(200, NULL, NULL, NULL, NULL),
(210, 'f2', '140', 'H', '2011'),
(220, 'f2222', '140000', 'HHH', '201111');
CREATE TABLE pordnrzu (
pordnr integer primary key,
pordnrzu integer
);
INSERT INTO pordnrzu (pordnr, pordnrzu)
VALUES
(112, 140),
(140, 210),
(200, 220),
(210, 220),
(220, NULL);
现在我的查询:
WITH RECURSIVE chain AS
(
SELECT n.pordnr, pz.pordnrzu, n.abschl, n.stg, n.kzfa, n.pversion
FROM pord n
LEFT JOIN pordnrzu pz
ON pz.pordnr = n.pordnr
WHERE n.pordnr = 112
UNION ALL
SELECT n.pordnr, pz2.pordnrzu, n.abschl, n.stg, n.kzfa, n.pversion
FROM chain c
LEFT JOIN pordnrzu pz2
ON pz2.pordnr = n.pordnr
INNER JOIN pord n ON (c.pordnrzu = n.pordnr)
WHERE c.abschl IS NULL
)
SELECT *
FROM chain c
WHERE c.abschl IS NOT NULL;
我的目标是从pordnr=112
开始,然后按pordnrzu
引导到其他pordnr
,直到找到第一个条目为abschl NOT NULL
在此示例中,解决方案将是此行:
pordnr pordnrzu abschl stg kzfa pversion
200 210 f2 140 H 2011
SELECT version();
x86_64-unknown-linux-gnu上的PostgreSQL 9.2.6,由gcc编译(SUSE Linux)4.3.4 [gcc-4_3-branch revision 152973],64位
答案 0 :(得分:1)
JOIN
子句的评估为left-to-right
。移动第二个联接以使其工作:
WITH RECURSIVE chain AS (
SELECT n.pordnr, pz.pordnrzu, n.abschl, n.stg, n.kzfa, n.pversion
FROM pord n
LEFT JOIN pordnrzu pz ON pz.pordnr = n.pordnr
WHERE n.pordnr = 112
UNION ALL
SELECT n.pordnr, pz.pordnrzu, n.abschl, n.stg, n.kzfa, n.pversion
FROM chain c
JOIN pord n ON n.pordnr = c.pordnrzu
LEFT JOIN pordnrzu pz ON pz.pordnr = n.pordnr
WHERE c.abschl IS NULL
)
SELECT *
FROM chain c
WHERE c.abschl IS NOT NULL;
或者,您可以在第二个SELECT中重写第一个JOIN:
LEFT JOIN pordnrzu pz ON pz.pordnr = c.pordnrzu