将表连接到PostgreSQL中其他表的递归查询。

huangapple go评论79阅读模式
英文:

join table to recursive query of other table in potresql

问题

我有两个表在PostgreSQL数据库中,它们之间有多对多的关系。

第一个表是Topic表,包含三列,它们的名称分别是id、name和parent。Topic表具有层次结构:

id name parent
1 Mathematics 0
2 Algebra 1
3 Progression 2
4 Number sequences 3
5 Arithmetics 1
6 sum values 5

第二个表名为task表,它包含两列 - task id和task text:

id task
100 1+2+3+4
101 1+2

tasks_topics表如下:

task_id topics_id
100 3
100 6
101 1

我需要将这两个表与Topic的递归查询联接起来。结果表应包含四列。第一列应该是task_id,第二列是task text,第三列是topic任务的所有父级名称,最后一列是父级topic的id。

结果应如下所示:

task_id name topics_name topics_id
100 1+2+3+4 sum values 6
100 1+2+3+4 Arithmetics 5
100 1+2+3+4 Progression 3
100 1+2+3+4 Algebra 2
100 1+2+3+4 Mathematics 1
101 1+2 Mathematics 1

我可以使用以下递归查询来获取Topic表的层次结构:

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;

但我不知道如何将它与task表通过id联接起来。你应该如何解决这个问题?

英文:

I have two tables with many to many relationship in Postresql database.

The first Topic table consists of three columns. Their names are id, name and parent. Topic table has hierarchial structure:

id name parent
1 Mathematics 0
2 Algebra 1
3 Progression 2
4 Number sequences 3
5 Arithmetics 1
6 sum values 5

The second table has name task table. It has two columns - task id and task text:

id task
100 1+2+3+4
101 1+2

tasks_topics table is

task_id topics_id
100 3
100 6
101 1

I need to get the table jointed to recursive query of topic. It should consists of four columns. THe first column should be task_id, the second task text, the third should be al parent names of topic tasks. And the last one should be parent topic id.

The result should be:

task_id name topics_name topics_id
100 1+2+3+4 sum values 6
100 1+2+3+4 Arithmetics 5
100 1+2+3+4 Progression 3
100 1+2+3+4 Algebra 2
100 1+2+3+4 Mathematics 1
101 1+2 Mathematics 1

I can make recursive query to topic table

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

;

but I don't know ho to join it to task by id.
How should I solve this problem?

答案1

得分: 1

第一个公共表达式(WITH RECURSIVE)用于获取主题的父级,cte2 用于将主题数组转换为行,然后我们将数据连接在一起以获得预期的结果。

演示链接在此处

英文:

First cte (WITH RECURSIVE) is to get topics parents,
cte2 to convert the array of topics to rows,
Then we join data together to get the expected result.

  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

答案2

得分: 0

以下是翻译好的代码部分:

_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)
)
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
英文:
_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)
)

should produce result as per below:

(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)

via SQL along these lines:

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

huangapple
  • 本文由 发表于 2023年2月24日 16:21:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75554124.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定