PostgreSQL key words of LATERAL

本文介绍了PostgreSQL中LATERAL子查询的功能和用法,通过实例对比了使用与未使用LATERAL关键字时的不同效果,展示了如何在一个子查询中引用另一个子查询的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文档解释:

FROM子句中出现的子查询可以放在关键字LATERAL之前,这样就允许它们引用通过前置FROM条目提供的字段。(如果没有LATERAL,那么每个子查询都被认为是独立的并且不能交叉引用任何其他的FROM条目。)

这是PostgreSQL9.3的新增特性,第一次看到这解释,估计看不懂,看下面解释。

1. 准备好的数据。

postgres=# select * from tb10;
 id | name1 
----+-------
  1 | aa
  2 | bb
  3 | cc
(3 rows)

postgres=# select * from tb11;
 id | name2 
----+-------
  1 | dd
  3 | ee
  5 | ff
(3 rows)

2. 如果没有LATERAL,那么每个子查询都被认为是独立的并且不能交叉引用任何其他的FROM条目。这句话的解释:

postgres=# select * from tb10 a inner join(select id,name2 from tb11)b on a.id=b.id;
 id | name1 | id | name2 
----+-------+----+-------
  1 | aa    |  1 | dd
  3 | cc    |  3 | ee
(2 rows)

这个是正常情况,这里有两个独立的from子查询,如果想在第二个子查询里面引用第一个子查询的数据,like the following:

postgres=# select * from tb10 a inner join(select id,name2,a.name1 from tb11)b on a.id=b.id;
ERROR:  invalid reference to FROM-clause entry for table "a"
LINE 1: select * from tb10 a inner join(select id,name2,a.name1 from...
                                                        ^
HINT:  There is an entry for table "a", but it cannot be referenced from this part of the query.

第二个子查询想引用第一个子查询的name1字段,提示错误,非法访问表a的from查询。

3. 使用LATERAL关键字:

postgres=# select * from tb10 a inner join lateral(select id,name2,a.name1 from tb11)b on a.id=b.id;
 id | name1 | id | name2 | name1 
----+-------+----+-------+-------
  1 | aa    |  1 | dd    | aa
  3 | cc    |  3 | ee    | cc
(2 rows)

可以看到,使用了LATERAL关键字之后,一个子查询可以访问与它并列的子查询的值。

现在来看文档的解释,”FROM子句中出现的子查询可以放在关键字LATERAL之前,这样就允许它们引用通过前置FROM条目提供的字段“,应该好理解一些。
 

### PostgreSQL LATERAL Join Usage and Examples In PostgreSQL, `LATERAL` joins allow for the evaluation of subqueries or functions with correlation to outer queries. This feature facilitates complex operations where each row generated by the left-hand side can produce multiple rows on the right-hand side through a function call or another query. #### Basic Syntax The basic syntax for using `LATERAL` involves placing it before a joined table when specifying how tables are connected within a FROM clause: ```sql SELECT * FROM left_table, LATERAL (subquery_or_function_call) AS right_alias; ``` This structure ensures that the subquery or function has access to columns from preceding items in the FROM list. #### Example Using Functions When working with arrays, similar to what was described regarding explode() taking in an array as input and outputting its elements as separate rows[^1], PostgreSQL offers various ways to achieve this behavior via `LATERAL`. For instance, consider having a JSONB column containing lists of values; one might want to unnest them into individual records per value while retaining context information like IDs associated originally. Here’s an example demonstrating how to expand nested data structures stored inside JSON documents: ```sql WITH sample_data(id, json_column) AS ( VALUES (1::int, '{"items": ["apple", "banana"]}'::jsonb), (2, '{"items": ["orange", "grape"]}'), (3, '{"items": []}') ) SELECT id, item FROM sample_data sd, LATERAL jsonb_array_elements_text(sd.json_column->'items') AS item; ``` Each element found under `"items"` key will generate new record alongside corresponding ID field thanks to lateral join mechanism allowing dynamic generation based upon content present at runtime rather than statically defined beforehand. #### Handling Aggregates Within LATERAL Joins For scenarios involving aggregates computed over dynamically produced sets—such as counting occurrences after expanding collections—one may combine windowing constructs along with aggregate functions directly within the `LATERAL` scope without needing explicit aliases for intermediate results mentioned elsewhere[^2]: ```sql WITH sales_by_customer(customer_id, orders) AS ( VALUES (101::int, ARRAY['book', 'pen']), (102, ARRAY['notebook']) ) SELECT customer_id, order_item, COUNT(*) OVER(PARTITION BY customer_id ORDER BY order_item) FROM sales_by_customer sc, LATERAL unnest(sc.orders) WITH ORDINALITY AS t(order_item); ``` Using `WITH ORDINALITY`, positions assigned during expansion provide additional flexibility useful especially when ordering matters post-expansion phase. #### Choosing Between UDFs/UDAFs vs Built-in Features While custom implementations offer great power, built-in features often suffice unless specific requirements necessitate bespoke logic beyond standard capabilities provided out-of-the-box. When considering whether implementing specialized routines such as those discussed concerning controlling row distribution towards single-user-defined-functions versus leveraging existing mechanisms available natively within SQL dialect being utilized should always weigh potential benefits against added complexity introduced thereby ensuring maintainable solutions remain feasible long term[^3]. --related questions-- 1. How does performance compare between native SQL methods and user-defined functions? 2. Can you explain practical applications of combining LATERAL joins with CTEs? 3. What considerations exist around memory usage when employing large-scale expansions via LATERAL? 4. Are there any limitations imposed by database versions affecting support for advanced JOIN types including LATERAL?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值