如何用SQL查询图结构中每个节点的直接邻居数量?
解决节点直接邻居数量统计的SQL查询方案
首先得明确核心需求:我们要统计的直接邻居是和当前节点有直接边连接的节点——不管这条边是从当前节点出发,还是指向当前节点,而且同一个邻居哪怕有多条重复边,也只能算一次。
思路拆解
要实现这个统计,我们需要:
- 把每条边的双向关系都覆盖到:既要看节点作为起点时连接的终点,也要看节点作为终点时连接的起点
- 对每个节点的关联邻居做去重处理,避免重复计数
- 确保所有顶点表中的节点都被统计到(哪怕某个节点没有任何边,也会显示计数为0,不过本题里所有节点都有邻居)
完整SQL查询语句
SELECT v.ID, COUNT(DISTINCT neighbor) AS COUNT FROM VERTEX v LEFT JOIN ( -- 收集节点作为起点时的邻居(终点) SELECT Source AS node, Target AS neighbor FROM EDGE UNION ALL -- 收集节点作为终点时的邻居(起点) SELECT Target AS node, Source AS neighbor FROM EDGE ) AS all_neighbors ON v.ID = all_neighbors.node GROUP BY v.ID ORDER BY v.ID;
语句细节解释
子查询
all_neighbors:- 第一部分把每条边的起点标记为
node,终点标记为neighbor,覆盖所有"节点→邻居"的正向关系 - 第二部分把每条边的终点标记为
node,起点标记为neighbor,覆盖所有"邻居→节点"的反向关系 - 用
UNION ALL合并这两部分,不会自动去重,保留所有原始关系,后续再统一处理去重
- 第一部分把每条边的起点标记为
主查询逻辑:
LEFT JOIN关联顶点表,保证所有顶点都能出现在结果里,不会因为没有边被遗漏COUNT(DISTINCT neighbor)对每个节点的邻居去重后计数,解决了多条重复边导致的重复统计问题GROUP BY v.ID按节点ID分组,完成每个节点的邻居数量统计
结果验证
执行上述查询后,会得到完全符合预期的输出:
ID | COUNT A | 3 B | 3 C | 1 D | 2 E | 1
对应题目里的邻居说明:
- A的邻居:E(来自E→A)、D(来自A→D)、B(多条边去重后算1次)
- B的邻居:A(多条边去重后算1次)、C(来自B→C)、D(多条边去重后算1次)
- C的邻居:B(来自B→C)
- D的邻居:B(多条边去重后算1次)、A(来自A→D)
- E的邻居:A(来自E→A)
内容的提问来源于stack exchange,提问作者Sumeet Kumar Yadav
相关产品推荐
相关产品推荐

