我不经常看到与 LATERAL 连接(PostgreSQL 11+)一起使用的 ON 子句。比如官方文档有这个例子:
LATERAL 的一个简单例子是
SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) ss;
这不是特别有用,因为它与更传统的结果完全相同
SELECT * FROM foo, bar WHERE bar.id = foo.bar_id;
从示例中,等效的常规连接有一个 ON 子句(使用 WHERE, 编写WHERE bar.id = foo.bar_id
),但对于 LATERAL JOIN,连接条件似乎是“内部化的”。
我觉得这个例子并不孤单。我看到许多没有 ON 子句的横向连接用法,但没有看到太多使用 ON 子句的情况。从概念上讲,横向连接是否需要 ON 子句尚不清楚,因为每组依赖值仅连接到它们所依赖的行。使用同一文档中的下一个示例来说明:
例如,假设 vertices(polygon) 返回多边形的顶点集,我们可以识别存储在表中的多边形的靠近在一起的顶点:
SELECT p1.id, p2.id, v1, v2
FROM polygons p1, polygons p2,
LATERAL vertices(p1.poly) v1,
LATERAL vertices(p2.poly) v2
WHERE (v1 <-> v2) < 10 AND p1.id != p2.id;
在这里,为每个多边形生成的顶点集p1.poly
仅与该多边形相关联,与任何其他多边形无关。似乎不需要使用 ON 子句指定计算结果与原始多边形之间的相关性。“连接条件”似乎隐含在横向连接中列的依赖关系中。
我无法从链接文档中找到确认是否需要使用 ON 子句,甚至是否允许 LATERAL JOIN。因此这个问题:
LATERAL JOIN 是否需要/允许连接条件(ON 子句)?
是的,只需摆脱以逗号分隔的 FROM 子句中列出表的古老方式:
这 ???标记原始查询错过 v1 和 p1 或 p2 之间的连接条件的位置
我不认为 LATERAL 在这里改变任何东西。
逗号连接或 CROSS JOIN 不能有 ON(如果有的话,您需要将条件填充到 WHERE 中),而其他显式 JOIN 类型需要 ON 或 USING。(我忽略了 NATURAL JOIN,这是理所当然的。)
如果您想在横向连接不返回任何行的情况下返回一个 NULL 扩展行,那么您可以使用
LEFT JOIN LATERAL (...) ON TRUE
. 除了 TRUE 之外的任何条件都不是必需的,因为您可以将其写入子查询本身(但如果它增加了与您还需要维护的其他查询的并行性,或者如果它只是很好地将要返回的行与是否返回任何行之间的逻辑分开)但是没有绝对的理由使用
JOIN LATERAL (...) ON TRUE
,因为您可以将其写为 CROSS JOIN LATERAL 代替。但同样,它可能以一种方式与另一种方式“看起来更好”。