</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> clause; this is not required, but otherwise the
<literal>WHERE</literal> clause will be fairly useless.
</para>
<note>
<para>
The join condition of an inner join can be written either in
the <literal>WHERE</literal> clause or in the <literal>JOIN</literal> clause.
For example, these table expressions are equivalent:
<programlisting>
FROM a, b WHERE a.id = b.id AND b.val > 5
</programlisting>
and:
<programlisting>
FROM a INNER JOIN b ON (a.id = b.id) WHERE b.val > 5
</programlisting>
or perhaps even:
<programlisting>
FROM a NATURAL JOIN b WHERE b.val > 5
</programlisting>
Which one of these you use is mainly a matter of style. The
<literal>JOIN</literal> syntax in the <literal>FROM</literal> clause is
probably not as portable to other SQL database management systems,
even though it is in the SQL standard. For
outer joins there is no choice: they must be done in
the <literal>FROM</literal> clause. The <literal>ON</literal> or <literal>USING</literal>
clause of an outer join is <emphasis>not</emphasis> equivalent to a
<literal>WHERE</literal> condition, because it results in the addition
of rows (for unmatched input rows) as well as the removal of rows
in the final result.
</para>
</note>
<para>
Here are some examples of <literal>WHERE</literal> clauses:
<programlisting>
SELECT ... FROM fdt WHERE c1 > 5
SELECT ... FROM fdt WHERE c1 IN (1, 2, 3)
SELECT ... FROM fdt WHERE c1 IN (SELECT c1 FROM t2)
SELECT ... FROM fdt WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10)
SELECT ... FROM fdt WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = fdt.c1 + 10) AND 100
SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1)
</programlisting>
<literal>fdt</literal> is the table derived in the
<literal>FROM</literal> clause. Rows that do not meet the search
condition of the <literal>WHERE</literal> clause are eliminated from
<literal>fdt</literal>. Notice the use of scalar subqueries as
value expressions. Just like any other query, the subqueries can
employ complex table expressions. Notice also how
<literal>fdt</literal> is referenced in the subqueries.
Qualifying <literal>c1</literal> as <literal>fdt.c1</literal> is only necessary
if <literal>c1</literal> is also the name of a column in the derived
input table of the subquery. But qualifying the column name adds
clarity even when it is not needed. This example shows how the column
naming scope of an outer query extends into its inner queries.
</para>
</sect2>
<sect2 id="queries-group">
<title>The <literal>GROUP BY</literal> and <literal>HAVING</literal> Clauses</title>
<indexterm zone="queries-group">
<primary>GROUP BY</primary>
</indexterm>
<indexterm zone="queries-group">
<primary>grouping</primary>
</indexterm>
<para>
After passing the <literal>WHERE</literal> filter, the derived