【问题标题】:Counting distinct undirected edges in a directed graph in SQL在 SQL 的有向图中计算不同的无向边
【发布时间】:2011-03-10 19:36:19
【问题描述】:

给定一个在有向图中保存边的表格,如下所示:

CREATE TABLE edges ( 
    from_here int not null, 
    to_there  int not null
)

获取特定节点的不同无向链接数量的最佳方法是什么?没有任何重复的有向边,也没有任何节点直接链接到自己,我只是想避免计算重复的无向边(例如(1,2)(2,1))两次。

这可行,但 NOT IN 对我来说很难闻:

SELECT COUNT(*)
FROM edges
WHERE from_here = 1
   OR (to_there = 1 AND from_here NOT IN (
        SELECT to_there 
        FROM edges 
        WHERE from_here = 1
   ))

PostgreSQL 特定的解决方案可以解决这个问题。

【问题讨论】:

  • 每条边都有互惠边吗?即,对于每个(1,2),必须存在一个(2,1)?
  • @Thomas:不,directed-edge-(1,2) 并不意味着directed-edge-(2,1),这两个有向边都可能出现,但只有一个是必要的。像 {(1,2),(1,3),(2,1)} 这样的边集应该产生 2 的计数(即取消对边的定向、折叠重复项、计算相关节点的无向​​度)。跨度>
  • 好的。那么我的第二个解决方案应该会给你你想要的。

标签: sql postgresql directed-graph


【解决方案1】:

如果每条边都有一个倒数(例如,如果(1,2) 存在,那么(2,1) 必须存在),那么您可以像这样简单地缩小您的列表:

 Select Count(*)
 From edges
 Where from_here < to_here
    And from_here = 1

如果我们不能假设互易边总是存在,那么您可以使用 except 谓词:

Select Count(*)
From    (
        Select from_here, to_there
        From edges
        Where from_here = 1
            Or to_there = 1
        Except
        Select to_there, from_here
        From edges
        Where from_here = 1
        ) As Z

【讨论】:

  • +10 用于教我一些新东西(即除了),但我会选择 UNION,因为它更简单。
【解决方案2】:
select count(*) from (
  select to_there from edges where from_here = 1
  union
  select from_here from edges where to_there = 1
) as whatever

【讨论】:

  • 对,“UNION 的结果不包含任何重复的行,除非指定了 ALL 选项。” (postgresql.org/docs/current/static/sql-select.html#SQL-UNION)。这将教会我不要使用 RTFM。
  • PostgreSQL(至少我的版本)想要一个别名为“(... union ...)”,但我会添加它并使用这个,因为这个 UNION 比 Thomas 的 EXCEPT 更简单.
【解决方案3】:
SELECT COUNT(DISTINCT CASE to_here WHEN 1 THEN from_here ELSE to_here END)
FROM edges
WHERE from_here = 1
   OR to_here = 1
/* or WHERE 1 IN (from_here, to_here) */

【讨论】:

    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多