【问题标题】:SQL Recursive query PostgresSQL 递归查询 Postgres
【发布时间】:2017-03-16 10:34:01
【问题描述】:

所以我有一个表 companyinfo 有这样的数据:

company |    role      |    person
--------|--------------|------------
Google  | dev          | John
Google  | tester       | Bob
Facebook| manager      | Alex
Facebook| blah         | Bob

我想通过约翰认识的人有多少“联系”来查找。因此,如果 John 和 Bob 在 Google 工作,John 通过 1 个连接认识 Bob,但如果 John 认识 Bob,Bob 认识 Alex,那么 John 也通过扩展认识 alex,但通过 Bob 意味着 2 个连接

我理解这是在代码中解决的非常简单的图形问题,但我一直在试图弄清楚如何编写递归 sql 来做到这一点几个小时,结果只是想出了:

WITH RECURSIVE search_graph(person, company, n) AS (
    SELECT s.person, s.company, 1
    FROM companyinfo s
    WHERE s.person = 'John'
  UNION
    SELECT s.person, s.company, n+1 
    FROM companyinfo s, search_graph sg
    WHERE s.person = 'Alex'
)
SELECT * FROM search_graph limit 50;

但它显然不起作用,是的,它确实找到了 Alex,但不是因为通过 bob 和循环跟踪连接不忠,因此 limit 50

澄清: 如果两个人在同一家公司工作,我们假设他们彼此认识。所以该图看起来像这样:

|John|--dev--|Google|--tester--|Bob|--blah--|Facebook|

因此人和公司是节点,角色是边缘。

【问题讨论】:

  • 你的表companyinfo没有任何关于人与人之间联系的信息。
  • 我应该澄清一下 - 在同一家公司工作的人彼此认识

标签: sql postgresql recursive-query


【解决方案1】:

基本查询是查找与给定人员在同一家公司工作的人,在 SQL 中它转换为 companyinfo 的自联接。此外,应该使用一组人员来消除重复。

with recursive search_graph(person, persons) as (
    select s2.person, array['John']
    from companyinfo s1
    join companyinfo s2 
    on s1.company = s2.company and s1.person <> s2.person
    where s1.person = 'John'
union
    select s2.person, persons || s1.person
    from companyinfo s1 
    join companyinfo s2 
    on s1.company = s2.company and s1.person <> s2.person
    join search_graph g 
    on s1.person = g.person
    where s1.person <> all(persons)
)
select distinct persons[cardinality(persons)] person, cardinality(persons) n
from search_graph
order by 2;

 person | n 
--------+---
 John   | 1
 Bob    | 2
 Alex   | 3
(3 rows)    

【讨论】:

  • 太棒了,但是order by 2 是做什么的?
  • order by n(按第二列排序)。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2014-10-29
  • 2020-11-27
  • 2015-07-13
  • 2014-12-19
  • 2012-12-05
  • 2016-01-25
相关资源
最近更新 更多