首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么PostgreSQL递归查询迭代不返回与手工创建的结果相同的结果?

为什么PostgreSQL递归查询迭代不返回与手工创建的结果相同的结果?
EN

Database Administration用户
提问于 2023-03-08 10:24:07
回答 1查看 67关注 0票数 0

我有以下测试表:

代码语言:javascript
复制
SELECT * FROM attempts order by id;

 id | user_id | name
----+---------+------
  1 |       1 | a
  2 |       2 | b
  3 |       1 | b
  4 |       1 | c
  5 |       2 | a
  6 |       1 | a
  7 |       1 | b
  8 |       1 | a
  9 |       3 | c
 10 |       4 | d
 11 |       3 | d
(11 rows)

我正在尝试调试下面的递归查询,因此我在结果集中打印出每个迭代id。

代码语言:javascript
复制
WITH RECURSIVE t(iter_id, id, user_id, name, aname, iname) AS (
  select 1, min(id) - 1, user_id, null, null, null as name from attempts group by user_id
UNION ALL
  select * from (
    with iter as (select * from t),
    t_min as (select min(id) as id from iter),
    next_id as (
      select min(attempts.id) as id
      from attempts
      left join iter using(name)
      where attempts.id > (select id from t_min)
      and iter.name is null
    )
    select iter.iter_id + 1, next_id.id, iter.user_id, coalesce(attempts.name, iter.name) as name, attempts.name aname, iter.name as iname
    from iter cross join next_id left join attempts
    on (attempts.id = next_id.id)
    and (attempts.user_id = iter.user_id)
    where next_id.id is not null
  ) as t2
)
select *
from t
order by iter_id, user_id, id
;

 iter_id | id | user_id | name | aname | iname
---------+----+---------+------+-------+-------
       1 |  0 |       1 | NULL | NULL  | NULL
       1 |  1 |       2 | NULL | NULL  | NULL
       1 |  8 |       3 | NULL | NULL  | NULL
       1 |  9 |       4 | NULL | NULL  | NULL
       2 |  1 |       1 | a    | a     | NULL
       2 |  1 |       2 | NULL | NULL  | NULL
       2 |  1 |       3 | NULL | NULL  | NULL
       2 |  1 |       4 | NULL | NULL  | NULL
       3 |  2 |       1 | a    | NULL  | a
       3 |  2 |       2 | b    | b     | NULL
       3 |  2 |       3 | NULL | NULL  | NULL
       3 |  2 |       4 | NULL | NULL  | NULL
       4 |  4 |       1 | c    | c     | a
       4 |  4 |       2 | b    | NULL  | b
       4 |  4 |       3 | NULL | NULL  | NULL
       4 |  4 |       4 | NULL | NULL  | NULL
       5 |  5 |       1 | c    | NULL  | c
       5 |  5 |       2 | a    | a     | b
       5 |  5 |       3 | NULL | NULL  | NULL
       5 |  5 |       4 | NULL | NULL  | NULL
       6 |  7 |       1 | b    | b     | c
       6 |  7 |       2 | a    | NULL  | a
       6 |  7 |       3 | NULL | NULL  | NULL
       6 |  7 |       4 | NULL | NULL  | NULL
       7 |  9 |       1 | b    | NULL  | b
       7 |  9 |       2 | a    | NULL  | a
       7 |  9 |       3 | c    | c     | NULL
       7 |  9 |       4 | NULL | NULL  | NULL
       8 | 10 |       1 | b    | NULL  | b
       8 | 10 |       2 | a    | NULL  | a
       8 | 10 |       3 | c    | NULL  | c
       8 | 10 |       4 | d    | d     | NULL
(32 rows)

我不明白为什么在迭代编号6上,下一个尝试id变成7而不是6。为了调试这个步骤,我创建了一个临时表,其值表示递归步骤5:

代码语言:javascript
复制
select * from tmp;

 id | user_id | name
----+---------+------
  5 |       1 | c
  5 |       2 | b
  5 |       3 | NULL
  5 |       4 | NULL
(4 rows)

当我对tmp表运行相同的查询时,我得到了预期的结果。

代码语言:javascript
复制
with iter as (select * from tmp),
t_min as (select min(id) as id from iter),
next_id as (
  select min(attempts.id) as id
  from attempts
  left join iter using(name)
  where attempts.id > (select id from t_min)
  and iter.name is null
)
select next_id.id, iter.user_id, coalesce(attempts.name, iter.name) as name, attempts.name aname, iter.name as iname
from iter cross join next_id left join attempts
on (attempts.id = next_id.id)
and (attempts.user_id = iter.user_id)
where next_id.id is not null
;

 id | user_id | name | aname | iname
----+---------+------+-------+-------
  6 |       1 | a    | a     | c
  6 |       2 | b    | NULL  | b
  6 |       3 | NULL | NULL  | NULL
  6 |       4 | NULL | NULL  | NULL
(4 rows)

为甚麽会有这样的差异呢?这是PostgreSQL中的一个可能的bug吗?

EN

回答 1

Database Administration用户

回答已采纳

发布于 2023-03-08 12:53:41

您将使用JOINing attemptsiter (name)。Name是您的3个文本列中的第一个列,在迭代5中它包含了ca,而不是cb,它们位于您命名为iname的最后一列上。

票数 2
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/324510

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档