我知道LATERAL加入可能能够帮助我,但即使在阅读来自Heap Analytics的文章(例如this one)后,我仍然不太明白。
LATERAL加入的用例是什么? LATERAL连接和子查询之间有什么区别?
LATERAL连接(Postgres 9.3)更像是一个correlated subquery,而不是一个普通的子查询。像@Andomar pointed out一样,LATERAL连接右侧的函数或子查询通常必须被评估多次 – 对于LATERAL连接的每一行,一次 – 就像一个相关的子查询,而一个纯子查询只被评估一次。这个相关的答案有并行的代码示例,解决同样的问题。
> Optimize GROUP BY query to retrieve latest record per user
当返回多个列时,LATERAL连接通常更简单,更清洁和更快。
另外,请记住,相关子查询的等价物是LEFT JOIN LATERAL .. ON TRUE:
> Call a set-returning function with an array argument multiple times
阅读手册
我强烈建议您阅读LATERAL的手册。它比我们将在这里提出的答案更有权威:
> http://www.postgresql.org/docs/current/interactive/queries-table-expressions.html#QUERIES-LATERAL
> http://www.postgresql.org/docs/current/interactive/sql-select.html
子查询不能做的事情
有一些事情,一个LATERAL连接可以做,但(相关)子查询不能(轻松)。相关子查询只能返回单个值,而不能返回多个列,而不返回多个行(除了裸函数调用(如果返回多行,则乘以结果行)。但是,即使某些set返回函数只允许在FROM子句中。像Postgres 9.4中带有多个参数的新的unnest()。 Per documentation:
This is only allowed in the FROM clause;
所以这工作,但不能轻易地替换为子查询:
CREATE TABLE tbl (a1 int[],a2 int[]); SELECT * FROM tbl t,unnest(t.a1,t.a2) u(elem1,elem2); -- implicit LATERAL
(FROM子句中的逗号(,)是CROSS JOIN的短标记。
对于诸如unnest()的表函数,自动假定为LATERAL。
更多关于UNNEST(array_expression [,…])的特殊情况下的关于dba.SE的后面的问题:
> How do you declare a set-returning-function to only be allowed in the FROM clause?
澄清错误信息
The manual clarifies misleading information here:
For the
INNER
andOUTER
join types,a join condition must be
specified,namely exactly one ofNATURAL
,ON
join_condition,
orUSING
(join_column [,…]). See below for the meaning.
ForCROSS JOIN
,none of these clauses can appear.
所以这些都是有效的(即使不是特别有用):
SELECT * FROM tbl t LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE; SELECT * FROM tbl t,LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
虽然这不是:
SELECT * FROM tbl t LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
这就是为什么@Andomar’s代码示例是正确的(CROSS JOIN不需要连接条件),@Attila’s是无效的。