@@ -50,10 +50,10 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replac
50
50
<phrase>where <replaceable class="parameter">from_item</replaceable> can be one of:</phrase>
51
51
52
52
[ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
53
- ( <replaceable class="parameter">select</replaceable> ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
53
+ [ LATERAL ] ( <replaceable class="parameter">select</replaceable> ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
54
54
<replaceable class="parameter">with_query_name</replaceable> [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
55
- <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] | <replaceable class="parameter">column_definition</replaceable> [, ...] ) ]
56
- <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
55
+ [ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] | <replaceable class="parameter">column_definition</replaceable> [, ...] ) ]
56
+ [ LATERAL ] <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
57
57
<replaceable class="parameter">from_item</replaceable> [ NATURAL ] <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> [ ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) ]
58
58
59
59
<phrase>and <replaceable class="parameter">with_query</replaceable> is:</phrase>
@@ -284,8 +284,8 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
284
284
The <literal>FROM</literal> clause specifies one or more source
285
285
tables for the <command>SELECT</command>. If multiple sources are
286
286
specified, the result is the Cartesian product (cross join) of all
287
- the sources. But usually qualification conditions
288
- are added to restrict the returned rows to a small subset of the
287
+ the sources. But usually qualification conditions are added (via
288
+ <literal>WHERE</>) to restrict the returned rows to a small subset of the
289
289
Cartesian product.
290
290
</para>
291
291
@@ -414,17 +414,18 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
414
414
</para>
415
415
416
416
<para>
417
- A <literal>JOIN</literal> clause combines two
418
- <literal>FROM</> items. Use parentheses if necessary to
419
- determine the order of nesting. In the absence of parentheses,
420
- <literal>JOIN</literal>s nest left-to-right. In any case
421
- <literal>JOIN</literal> binds more tightly than the commas
422
- separating <literal>FROM</> items.
417
+ A <literal>JOIN</literal> clause combines two <literal>FROM</>
418
+ items, which for convenience we will refer to as <quote>tables</>,
419
+ though in reality they can be any type of <literal>FROM</> item.
420
+ Use parentheses if necessary to determine the order of nesting.
421
+ In the absence of parentheses, <literal>JOIN</literal>s nest
422
+ left-to-right. In any case <literal>JOIN</literal> binds more
423
+ tightly than the commas separating <literal>FROM</>-list items.
423
424
</para>
424
425
425
426
<para><literal>CROSS JOIN</> and <literal>INNER JOIN</literal>
426
427
produce a simple Cartesian product, the same result as you get from
427
- listing the two items at the top level of <literal>FROM</>,
428
+ listing the two tables at the top level of <literal>FROM</>,
428
429
but restricted by the join condition (if any).
429
430
<literal>CROSS JOIN</> is equivalent to <literal>INNER JOIN ON
430
431
(TRUE)</>, that is, no rows are removed by qualification.
@@ -449,7 +450,7 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
449
450
joined rows, plus one row for each unmatched right-hand row
450
451
(extended with nulls on the left). This is just a notational
451
452
convenience, since you could convert it to a <literal>LEFT
452
- OUTER JOIN</> by switching the left and right inputs .
453
+ OUTER JOIN</> by switching the left and right tables .
453
454
</para>
454
455
455
456
<para><literal>FULL OUTER JOIN</> returns all the joined rows, plus
@@ -495,6 +496,47 @@ TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ]
495
496
</para>
496
497
</listitem>
497
498
</varlistentry>
499
+
500
+ <varlistentry>
501
+ <term><literal>LATERAL</literal></term>
502
+ <listitem>
503
+ <para>The <literal>LATERAL</literal> key word can precede a
504
+ sub-<command>SELECT</command> or function-call <literal>FROM</>
505
+ item. This allows the sub-<command>SELECT</command> or function
506
+ expression to refer to columns of <literal>FROM</> items that appear
507
+ before it in the <literal>FROM</> list. (Without
508
+ <literal>LATERAL</literal>, each <literal>FROM</> item is evaluated
509
+ independently and so cannot cross-reference any other
510
+ <literal>FROM</> item.) A <literal>LATERAL</literal> item can
511
+ appear at top level in the <literal>FROM</> list, or within a
512
+ <literal>JOIN</> tree; in the latter case it can also refer to any
513
+ items that are on the left-hand side of a <literal>JOIN</> that it is
514
+ on the right-hand side of.
515
+ </para>
516
+
517
+ <para>
518
+ When a <literal>FROM</> item contains <literal>LATERAL</literal>
519
+ cross-references, evaluation proceeds as follows: for each row of the
520
+ <literal>FROM</> item providing the cross-referenced column(s), or
521
+ set of rows of multiple <literal>FROM</> items providing the
522
+ columns, the <literal>LATERAL</literal> item is evaluated using that
523
+ row or row set's values of the columns. The resulting row(s) are
524
+ joined as usual with the rows they were computed from. This is
525
+ repeated for each row or set of rows from the column source table(s).
526
+ </para>
527
+
528
+ <para>
529
+ The column source table(s) must be <literal>INNER</> or
530
+ <literal>LEFT</> joined to the <literal>LATERAL</literal> item, else
531
+ there would not be a well-defined set of rows from which to compute
532
+ each set of rows for the <literal>LATERAL</literal> item. Thus,
533
+ although a construct such as <literal><replaceable>X</> RIGHT JOIN
534
+ LATERAL <replaceable>Y</></literal> is syntactically valid, it is
535
+ not actually allowed for <replaceable>Y</> to reference
536
+ <replaceable>X</>.
537
+ </para>
538
+ </listitem>
539
+ </varlistentry>
498
540
</variablelist>
499
541
</para>
500
542
</refsect2>
@@ -1532,6 +1574,26 @@ SELECT distance, employee_name FROM employee_recursive;
1532
1574
else the query will loop indefinitely. (See <xref linkend="queries-with">
1533
1575
for more examples.)
1534
1576
</para>
1577
+
1578
+ <para>
1579
+ This example uses <literal>LATERAL</> to apply a set-returning function
1580
+ <function>get_product_names()</> for each row of the
1581
+ <structname>manufacturers</> table:
1582
+
1583
+ <programlisting>
1584
+ SELECT m.name AS mname, pname
1585
+ FROM manufacturers m, LATERAL get_product_names(m.id) pname;
1586
+ </programlisting>
1587
+
1588
+ Manufacturers not currently having any products would not appear in the
1589
+ result, since it is an inner join. If we wished to include the names of
1590
+ such manufacturers in the result, we could do:
1591
+
1592
+ <programlisting>
1593
+ SELECT m.name AS mname, pname
1594
+ FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true;
1595
+ </programlisting>
1596
+ </para>
1535
1597
</refsect1>
1536
1598
1537
1599
<refsect1>
@@ -1611,6 +1673,20 @@ SELECT distributors.* WHERE distributors.name = 'Westward';
1611
1673
</para>
1612
1674
</refsect2>
1613
1675
1676
+ <refsect2>
1677
+ <title>Function Calls in <literal>FROM</literal></title>
1678
+
1679
+ <para>
1680
+ <productname>PostgreSQL</productname> allows a function call to be
1681
+ written directly as a member of the <literal>FROM</> list. In the SQL
1682
+ standard it would be necessary to wrap such a function call in a
1683
+ sub-<command>SELECT</command>; that is, the syntax
1684
+ <literal>FROM <replaceable>func</>(...) <replaceable>alias</></literal>
1685
+ is approximately equivalent to
1686
+ <literal>FROM (SELECT <replaceable>func</>(...)) <replaceable>alias</></literal>.
1687
+ </para>
1688
+ </refsect2>
1689
+
1614
1690
<refsect2>
1615
1691
<title>Namespace Available to <literal>GROUP BY</literal> and <literal>ORDER BY</literal></title>
1616
1692
0 commit comments