我正在try 为我的递归查询创建一个视图,并使用带有WHERE子句的视图来设置起点.

CREATE TABLE dog (
    id int,
    name varchar(50)
)

CREATE TABLE dog_parent (
    id int,
    dog_id int,
    parent_id int,
)

这个递归查询返回我所期望的结果

WITH recursive Ancestor_Tree AS (
    SELECT 
        mp.dog_id,
        mp.parent_id
    FROM
        dog_parent mp
    WHERE mp.dog_id = 26

    UNION ALL

    SELECT
        mp.dog_id,
        mp.parent_id
    FROM
        dog_parent mp,
        Ancestor_Tree ft
    WHERE mp.dog_id = ft.parent_id
)

SELECT 
    ft.dog_id,
    mm.name AS Member,
    ft.parent_id,
    mp.name AS Parent
FROM Ancestor_Tree ft
INNER JOIN dog mm
    ON mm.id = ft.dog_id
INNER JOIN dog mp
    ON mp.id = ft.parent_id

结果:

| dog_id | member     | parent_id | parent         |
| ------ | ---------- | --------- | -------------- |
| 33     | Beniga     | 35        | Bunta          |
| 33     | Beniga     | 36        | Kaori          |
| 26     | Rei        | 33        | Beniga         |
| 34     | Ginga      | 37        | Gouzanhaou     |
| 34     | Ginga      | 38        | Ukigumo        |
| 26     | Rei        | 34        | Ginga          |
| 38     | Ukigumo    | 39        | Kumotarou      |
| 38     | Ukigumo    | 40        | Gintsurugihime |
| 37     | Gouzanhaou | 41        | Gyokuhou       |
| 35     | Bunta      | 42        | Koharu         |
| 35     | Bunta      | 43        | Chouhou        |
| 43     | Chouhou    | 44        | Kotofusa       |
| 43     | Chouhou    | 45        | Tsubomi        |
| 36     | Kaori      | 46        | Chacha         |
| 46     | Chacha     | 47        | Teruhide       |
| 46     | Chacha     | 48        | Sekihoume      |
| 36     | Kaori      | 49        | Kokuga         |
| 49     | Kokuga     | 50        | Kotokaze       |
| 50     | Kotokaze   | 51        | Seizanhou      |
| 50     | Kotokaze   | 52        | Houki          |

但我想要创建一个VIEW,并用WHERE代替WHERE mp.dog_id = 26,就像这样:

SELECT * FROM recursive_view WHERE dog_id = 26

以下是我try 创建该视图的方式:

CREATE OR REPLACE VIEW recursive_view AS
WITH recursive Ancestor_Tree (dog_id, parent_id) AS (
    SELECT 
        mp.dog_id as dog_id,
        mp.parent_id as parent_id
    FROM
        dog_parent mp

    UNION ALL

    SELECT
        mp.dog_id,
        mp.parent_id
    FROM
        dog_parent mp,
        Ancestor_Tree ft
    WHERE mp.dog_id = ft.parent_id
)

SELECT 
    ft.dog_id,
    mm.name AS Member,
    ft.parent_id,
    mp.name AS Parent
FROM Ancestor_Tree ft
INNER JOIN dog mm
    ON mm.id = ft.dog_id
INNER JOIN dog mp
    ON mp.id = ft.parent_id

但当我用SELECT * FROM recursive_view WHERE dog_id = 26调用它时,我只得到狗26的父母,而不是递归部分.

结果:

| dog_id | member     | parent_id | parent         |
| ------ | ---------- | --------- | -------------- |
| 26     | Rei        | 33        | Beniga         |
| 26     | Rei        | 34        | Ginga          |

对于这个接受WHERE子句的递归查询,我如何才能得到VIEW呢?

推荐答案

对于简单的视图,其中输出列可以直接映射到输入列,查询规划器可以将谓词下推到输入表.但在这种情况下,输出列dog_id不能直接映射到输入列dog_parent.dog_id,因此这是不可能的.

在您try 的查询中:

SELECT * FROM recursive_view WHERE dog_id = 26

...过滤器WHERE dog_id = 26被应用after个结果行已经被递归地(实际上是迭代地)生成到输出列.

VIEW分是你目标的wrong tool分.您想要将运行递归项的过滤器before应用于输入列.为此,请使用集返回FUNCTIONprepared statement.喜欢:

CREATE OR REPLACE FUNCTION f_ancestors_of(_dog_id int)  -- !!!
  RETURNS TABLE (
    dog_id int
  , member text
  , parent_id int
  , parent int
  )
  LANGUAGE sql AS
$func$
WITH RECURSIVE ancestor_tree AS (
    SELECT
        mp.dog_id,
        mp.parent_id
    FROM
        dog_parent mp
    WHERE mp.dog_id = _dog_id  -- !!!

    UNION ALL
    SELECT
        mp.dog_id,
        mp.parent_id
    FROM
        dog_parent mp,
        ancestor_tree ft
    WHERE mp.dog_id = ft.parent_id
   )
SELECT
    ft.dog_id,
    mm.name AS member,
    ft.parent_id,
    mp.name AS parent
FROM ancestor_tree ft
INNER JOIN dog mm
    ON mm.id = ft.dog_id
INNER JOIN dog mp
    ON mp.id = ft.parent_id
$func$;

电话:

SELECT * FROM f_ancestors_of(26);

相关:

Postgresql相关问答推荐

如何在gorm中创建一个可读但不可写的字段

到第二天的Postgres计时器

无法在kubernetes中设置postgres复制

将具有自定义类型的表从一种模式复制到另一种模式

为什么我的唯一索引在 Postgresql 中不起作用?

PostgreSQL 连接字符串的正则表达式

使用doobie,如何将Scala case类映射到带有类型tstzmultirange的PostgreSQL列?

查找行中的最小值

PostgreSQL错误致命:角色 username不存在

使用 ON CONFLICT 从 INSERT 返回行,无需更新

我应该使用哪个 postgresql 包?

使用 RPostgreSQL 进行 UTF-8 / Unicode 文本编码

如果 Column1 不为空,则按 Column1 排序,否则按 Column2 排序

SQL Select 一列中具有重复值的所有行

在 Spring Boot 应用程序中禁用表重新创建

如何为 postgres 连接设置 application_name?

如何使用 PostgreSQL 触发器来存储更改(SQL 语句和行更改)

SQL:子查询的列太多

如何更改 PostgreSQL 中的 REFERENCES?

postgres LISTEN/NOTIFY rails