【问题标题】:Recursive chain with JOIN element?带有 JOIN 元素的递归链?
【发布时间】:2014-02-18 14:06:10
【问题描述】:

我最近在 postgreSQL 中请求recursive query。答案很合适,但是一旦我添加了一个 JOIN 元素,它就会给我以下错误:

错误:表“n”缺少 FROM 子句条目:WITH RECURSIVE 链 作为(选择 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 从链 c 左连接 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 空

我尝试了几次修改,但无法使其正常工作。我想要的是,正在实施 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 位

【问题讨论】:

    标签: sql postgresql join recursive-cte


    【解决方案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;
    

    或者,您可以在 2nd SELECT 中重写 1st JOIN:

    LEFT   JOIN pordnrzu pz ON pz.pordnr = <b>c.pordnrzu</b>

    【讨论】:

    • 好的,可以了,谢谢!你能解释一下为什么我需要在第二个 SELECT 中进行第二个 JOIN 吗?那简直太好了。 :)
    • 要从下一个pord 检索数据,您需要加入它。不知道还有什么要解释的?我添加了一个替代方案...
    • 好吧,我明白了。 :) 但我不明白为什么我在前一个问题上不需要它。 stackoverflow.com/questions/21674589/… 但我会重新阅读它,因为我现在满脑子都是疑问。 :D 再次感谢您的帮助!
    • @Trollwut:你之前的问题也是这样。唯一的区别是附加表pordnrzu,您可以在其中存储指向此模型中下一个节点的链接。
    猜你喜欢
    • 2022-06-28
    • 2021-05-29
    • 2021-03-23
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多