sql - 在 PostgreSQL 中创建最佳图形关系

标签 sql algorithm postgresql graph plpgsql

我在 PostgreSQL 中有一个表,它包含两列,第一个 ID 和第二个 ID。其中的每一项都意味着第一个ID和第二个ID之间存在关系,并且可以保证第一个ID总是大于第二个ID。

我的目标是处理表格,以便它可以检测网络(相互关联的多个 ID),并更改表格中该网络的每个关系,以便第一个 ID 是网络中的大 ID,第二个ID始终是网络中最小的ID。
示例:

D->C , C->B , B->A , F->E , H->G

将成为:

D->A , C->A , B->A , F->E , H->G

另一个例子:

D->C , D->B , D->A

将成为:

D->A , C->A , B->A

如何使用 SQL 或 Postgres 过程语言来做到这一点?

编辑:我使用的 PostgreSQL 版本是 9.4。该表由列id1(整数)和id2(整数)组成,它们都是主键。

关于如何断定A是第二个例子集合(A,B,C)中最小的,我用这个查询来确定最小的id2

SELECT id1, MIN(id2) FROM table GROUP BY id1

最佳答案

假设有这样一张表:

CREATE TABLE tbl (
  id1 int
, id2 int
, PRIMARY KEY (id1, id2)
);

根据您的逻辑,循环引用是不可能的。

recursive CTE会做的工作:

WITH RECURSIVE cte AS (
   SELECT t1.id1, t1.id2, t2.id2 AS next_id2
   FROM   tbl t1
   LEFT   JOIN tbl t2 ON t2.id1 = t1.id2

   UNION ALL
   SELECT t1.id1, t1.next_id2, t2.id2
   FROM   cte t1
   LEFT   JOIN tbl t2 ON t2.id1 = t1.next_id2
   WHERE  t1.next_id2 IS NOT NULL  -- stop iterating at end of graph
   )
SELECT id1, id2
FROM   cte
WHERE  next_id2 IS NULL;  -- only rows where the graph ends

在非递归术语中,选择每一行 并尝试使用LEFT JOIN 找到下一步。

在递归项中,用下一步替换第二个 ID,直到我们到达图的末尾(next_id2 IS NULL)。

在外部 SELECT 中只返回图表结束的行。以任意排序顺序产生结果。

如果图可以 fork ,您还不清楚如何确定最深的兔子洞。

关于sql - 在 PostgreSQL 中创建最佳图形关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36255607/

相关文章:

mysql - SQL查询检查之前和之后检查获取最近的日期

c# - 特定客户的最后订单记录 - SQL

algorithm - 指数的时间复杂度

sql - 从 bool 列 postgresql 创建 varchar 列

java - Postgres DB 触发器调用 Java 函数

database - 为什么两个表不能有同名索引?

mysql - 使用替换查询在 mysql 中将 "And"替换为 "and"

c# - 将 datetimepicker 值传递给 C# 中的 WHERE LIKE 子句

c# - 有没有一种好的方法来优化迭代次数相乘的嵌套 for 循环?

java - 大 O 符号和带循环的递归