Hans-Juergen Schoenig:PostgreSQL 19 中 SQL/PGQ 的异构图查询

Hans-Juergen Schoenig:PostgreSQL 19 中 SQL/PGQ 的异构图查询

💡 原文英文,约800词,阅读约需3分钟。
📝

内容提要

本文介绍 PostgreSQL 19 中 SQL/PGQ 图查询的进阶用法:以人物、公司为顶点,knows、works_at 为边构建属性图,演示查询 Alice 朋友的就职公司及查找互相认识的同事。因 PG19 暂不支持逗号分隔的多模式匹配,需先用 GRAPH_TABLE 输出 ID 再 JOIN;多边表图应显式命名边标签,变长跳数 {1,3} 语法暂未支持。

🔎

延伸解读

多表属性图的建模要点

文章示例将人物和公司分别作为顶点表,knows 和 works_at 作为边表,构建跨表属性图。这种设计允许在单一图中表达社交与职业关系。读者需注意,边表可以连接相同类型的顶点(如人物-人物),也可以连接不同类型的顶点(如人物-公司),这为复杂查询奠定了基础。

PG19 多模式匹配的变通方案

PostgreSQL 19 尚未支持在 MATCH 中使用逗号分隔的多模式匹配,这是标准语法但实现未跟上。文章给出的变通方案是:先用 GRAPH_TABLE 查询并输出所需 ID,再通过普通 SQL JOIN 关联结果。这种方法虽然不如标准语法简洁,但能有效解决多模式查询需求,且 GRAPH_TABLE 的输出可作为普通表使用。

多边表图必须显式命名边标签

在包含多个边表的图中,若省略边标签(如直接写 (a)->(b)),查询会混合所有边类型,导致意外结果。文章示例中,匿名形式会同时匹配 knows 和 works_at 边,产生 9 条 knows 边和 7 条 works_at 边的组合。因此,对于多边表图,务必使用 [IS knows] 等语法明确指定边标签,避免逻辑错误。

变长跳数语法尚未支持

文章指出,PostgreSQL 19 暂不支持 {1,3} 这样的变长跳数语法,该功能仍在路线图中。目前若需实现多跳查询,可采取两种替代方案:一是显式展开,每个跳数单独使用 GRAPH_TABLE 并通过 UNION 合并;二是回退到基于底层边表的 WITH RECURSIVE 查询。这两种方法均可行,但不如未来的 {1,3} 语法优雅。

Q&A

PostgreSQL 19 的 SQL/PGQ 如何定义包含人物和公司的异构图?

在 PostgreSQL 19 中,可以定义属性图,其中顶点来自人物和公司两个表,边来自 knows 和 works_at 两个表。knows 连接人物与人物,works_at 连接人物与公司。定义时需暴露所需属性,并为边指定标签。

在 PostgreSQL 19 中,如何用 SQL/PGQ 查询 Alice 朋友的就职公司?

使用 GRAPH_TABLE 和 MATCH 子句,从 Alice 出发,通过 knows 边找到朋友,再通过 works_at 边找到公司,最后在 COLUMNS 中输出公司信息。可以在 MATCH 内使用 WHERE 过滤 Alice。

PostgreSQL 19 的 SQL/PGQ 支持在一个 MATCH 中写多个逗号分隔的模式吗?如果不支持,有什么变通方法?

不支持。PostgreSQL 19 尚未实现标准中的多模式匹配。变通方法是先用 GRAPH_TABLE 查询出需要的 ID,然后通过普通 SQL JOIN 将这些 ID 与其他表连接。

在 PostgreSQL 19 的 SQL/PGQ 中,多边表图如果不显式命名边标签会有什么问题?

在多边表图中,如果省略边标签(如 (a)->(b)),查询会混合所有边类型,导致结果错误。例如在 company_social 图中,会同时匹配 knows 和 works_at 边,产生笛卡尔积。应始终显式命名边标签。

PostgreSQL 19 的 SQL/PGQ 支持变长跳数语法如 {1,3} 吗?如果不支持,如何实现多跳查询?

不支持。目前变长跳数语法仍在路线图中。替代方案有两种:一是对每个跳数单独写 GRAPH_TABLE 并用 UNION 合并;二是回退到使用 WITH RECURSIVE 在底层边表上递归查询。

在 PostgreSQL 19 的 SQL/PGQ 中,如何查找互相认识的同事?

由于不支持多模式匹配,需要先用 GRAPH_TABLE 分别查询出同事关系和认识关系,提取人物 ID,然后通过 SQL JOIN 将结果连接,筛选出互相认识的同事对。

🏷️

标签

➡️

继续阅读