the
<literal>FROM</literal> list, or within a <literal>JOIN</literal> tree. In the latter
case it can also refer to any items that are on the left-hand side of a
<literal>JOIN</literal> that it is on the right-hand side of.
</para>
<para>
When a <literal>FROM</literal> item contains <literal>LATERAL</literal>
cross-references, evaluation proceeds as follows: for each row of the
<literal>FROM</literal> item providing the cross-referenced column(s), or
set of rows of multiple <literal>FROM</literal> items providing the
columns, the <literal>LATERAL</literal> item is evaluated using that
row or row set's values of the columns. The resulting row(s) are
joined as usual with the rows they were computed from. This is
repeated for each row or set of rows from the column source table(s).
</para>
<para>
A trivial example of <literal>LATERAL</literal> is
<programlisting>
SELECT * FROM foo, LATERAL (SELECT * FROM bar WHERE bar.id = foo.bar_id) ss;
</programlisting>
This is not especially useful since it has exactly the same result as
the more conventional
<programlisting>
SELECT * FROM foo, bar WHERE bar.id = foo.bar_id;
</programlisting>
<literal>LATERAL</literal> is primarily useful when the cross-referenced
column is necessary for computing the row(s) to be joined. A common
application is providing an argument value for a set-returning function.
For example, supposing that <function>vertices(polygon)</function> returns the
set of vertices of a polygon, we could identify close-together vertices
of polygons stored in a table with:
<programlisting>
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;
</programlisting>
This query could also be written
<programlisting>
SELECT p1.id, p2.id, v1, v2
FROM polygons p1 CROSS JOIN LATERAL vertices(p1.poly) v1,
polygons p2 CROSS JOIN LATERAL vertices(p2.poly) v2
WHERE (v1 <-> v2) < 10 AND p1.id != p2.id;
</programlisting>
or in several other equivalent formulations. (As already mentioned,
the <literal>LATERAL</literal> key word is unnecessary in this example, but
we use it for clarity.)
</para>
<para>
It is often particularly handy to <literal>LEFT JOIN</literal> to a
<literal>LATERAL</literal> subquery, so that source rows will appear in
the result even if the <literal>LATERAL</literal> subquery produces no
rows for them. For example, if <function>get_product_names()</function> returns
the names of products made by a manufacturer, but some manufacturers in
our table currently produce no products, we could find out which ones
those are like this:
<programlisting>
SELECT m.name
FROM manufacturers m LEFT JOIN LATERAL get_product_names(m.id) pname ON true
WHERE pname IS NULL;
</programlisting>
</para>
</sect3>
</sect2>
<sect2 id="queries-where">
<title>The <literal>WHERE</literal> Clause</title>
<indexterm zone="queries-where">
<primary>WHERE</primary>
</indexterm>
<para>
The syntax of the <link linkend="sql-where"><literal>WHERE</literal></link>
clause is
<synopsis>
WHERE <replaceable>search_condition</replaceable>
</synopsis>
where <replaceable>search_condition</replaceable> is any value
expression (see <xref linkend="sql-expressions"/>) that
returns a value of type <type>boolean</type>.
</para>
<para>
After the processing of the <literal>FROM</literal> clause is done, each
row of the derived virtual table is checked against the search
condition. If the result of the condition is true, the row is
kept in the output table, otherwise (i.e., if the result is
false or null) it is discarded. The search condition typically
references at least one column of the table generated in the
<literal>FROM</literal>