SQL 递归查询 Postgres
SQL Recursive query Postgres
所以我有一个 table 公司信息,其数据如下:
company | role | person
--------|--------------|------------
Google | dev | John
Google | tester | Bob
Facebook| manager | Alex
Facebook| blah | Bob
我想通过 "connections" 约翰认识多少人。因此,如果 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|
这样,人和公司就是节点,角色就是边。
基本查询是查找与给定人员在同一家公司工作的人员,在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)
所以我有一个 table 公司信息,其数据如下:
company | role | person
--------|--------------|------------
Google | dev | John
Google | tester | Bob
Facebook| manager | Alex
Facebook| blah | Bob
我想通过 "connections" 约翰认识多少人。因此,如果 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|
这样,人和公司就是节点,角色就是边。
基本查询是查找与给定人员在同一家公司工作的人员,在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)