postgresql 将表连接到potresql中其他表的递归查询

t1qtbnec  于 2023-03-01  发布在  PostgreSQL
关注(0)|答案(2)|浏览(137)

我在Postresql数据库中有两个具有多对多关系的表。
第一个主题表由三列组成。它们的名称分别为id、name和parent。主题表具有层次结构:
| 身份证|姓名|母体|
| - ------|- ------|- ------|
| 1个|数学|无|
| 第二章|代数|1个|
| 三个|进展|第二章|
| 四个|数列|三个|
| 五个|算术|1个|
| 六个|和值|五个|
第二个表具有名称任务表。它具有两列-任务ID和任务文本:
| 身份证|任务|
| - ------|- ------|
| 一百|1 + 2 + 3 + 4|
| 一百零一|一加二|
任务主题表为
| 任务标识|主题ID|
| - ------|- ------|
| 一百|三个|
| 一百|六个|
| 一百零一|1个|
我需要得到连接到主题递归查询的表。它应该由四列组成。第一列应该是任务ID,第二列是任务文本,第三列应该是主题任务的所有父名称。最后一列应该是父主题ID。
结果应为:
| 任务标识|姓名|主题名称|主题ID|
| - ------|- ------|- ------|- ------|
| 一百|1 + 2 + 3 + 4|和值|六个|
| 一百|1 + 2 + 3 + 4|算术|五个|
| 一百|1 + 2 + 3 + 4|进展|三个|
| 一百|1 + 2 + 3 + 4|代数|第二章|
| 一百|1 + 2 + 3 + 4|数学|1个|
| 一百零一|一加二|数学|1个|
我可以递归查询主题表

WITH RECURSIVE topic_parent AS (
  SELECT 
    id, 
    name, 
    parent 
  FROM 
    topics 
  WHERE 
    id = 3 
  UNION 
  SELECT 
    topics.id, 
    topics.name, 
    topics.parent 
  FROM 
    topics 
    INNER JOIN topic_parent ON topic_parent.parent = topics.id
) 
SELECT 
  * 
FROM 
  topic_parent

;
但是我不知道如何通过id将它加入任务。我应该如何解决这个问题?

yqlxgs2m

yqlxgs2m1#

首先,cte(WITH RECURSIVE)用于获取主题父项,cte2用于将主题数组转换为行,然后我们将数据连接在一起以获得预期结果。

WITH RECURSIVE topic_parent(id, path) AS (
  SELECT 
    id, ARRAY[id]
  FROM topics 
  WHERE parent = 0
  UNION 
  SELECT 
    t.id, path || t.id
  FROM 
    topics t
    INNER JOIN topic_parent rt ON rt.id = t.parent
),
cte2 as (
  select *, unnest(path) AS linked_id
  from topic_parent
)
select task_id, max(task) as task_name, max(name) as topic_name, linked_id as topic_id
from cte2 c
inner join tasks_topics t on c.id = t.topics_id
inner join tasks t2 on t2.id = t.task_id
inner join topics t3 on t3.id = c.linked_id
group by task_id, linked_id
order by task_id asc, linked_id desc

Demo here

7tofc5zh

7tofc5zh2#

_task_id = 100
topics_from = (
    session.query(Tasks, Topics)
    .join(Topics, Tasks.topics)
    .filter(Tasks.id == _task_id)  # optional
).cte(name="alltopic", recursive=True)

# union or union_all depending on if you want to filter out duplicates (top level)
allq = topics_from.union(
    session.query(Tasks, Topics)
    .filter(Topics.id == topics_from.c.parent_id)
    .filter(Tasks.id == topics_from.c.id)
)

应产生如下结果:

(100, '1+2+3+4', 5, 'sum values', 3)
(100, '1+2+3+4', 6, 'Number sequences', 4)
(100, '1+2+3+4', 3, 'Arithmetics', 1)
(100, '1+2+3+4', 4, 'Progression', 2)
(100, '1+2+3+4', 1, 'Mathematics', 0)
(100, '1+2+3+4', 2, 'Algebra', 1)

通过SQL沿着以下操作:

WITH RECURSIVE alltopic(id, task, id_1, name, parent_id) AS
  (SELECT tasks.id AS id,
          tasks.task AS task,
          topics.id AS id_1,
          topics.name AS name,
          topics.parent_id AS parent_id
   FROM tasks
   JOIN tasks_topics AS tasks_topics_1 ON tasks.id = tasks_topics_1.task_id
   JOIN topics ON topics.id = tasks_topics_1.topics_id
                topics.parent_id AS topics_parent_id
   FROM tasks,
        topics,
        alltopic
   WHERE topics.id = alltopic.parent_id
     AND tasks.id = alltopic.id)
SELECT alltopic.id,
       alltopic.task,
       alltopic.id_1,
       alltopic.name,
       alltopic.parent_id
FROM alltopic

相关问题