Home Explore Blog CI



postgresql

29th chunk of `doc/src/sgml/queries.sgml`
1f221333479aeeb97a378f63bf65e60fd10c6f10f4ef4e180000000100000fa1
 columns
    and using that to sort the results at the end.  Note that this does not
    actually control in which order the query evaluation visits the rows; that
    is as always in SQL implementation-dependent.  This approach merely
    provides a convenient way to order the results afterwards.
   </para>

   <para>
    To create a depth-first order, we compute for each result row an array of
    rows that we have visited so far.  For example, consider the following
    query that searches a table <structname>tree</structname> using a
    <structfield>link</structfield> field:

<programlisting>
WITH RECURSIVE search_tree(id, link, data) AS (
    SELECT t.id, t.link, t.data
    FROM tree t
  UNION ALL
    SELECT t.id, t.link, t.data
    FROM tree t, search_tree st
    WHERE t.id = st.link
)
SELECT * FROM search_tree;
</programlisting>

    To add depth-first ordering information, you can write this:

<programlisting>
WITH RECURSIVE search_tree(id, link, data, <emphasis>path</emphasis>) AS (
    SELECT t.id, t.link, t.data, <emphasis>ARRAY[t.id]</emphasis>
    FROM tree t
  UNION ALL
    SELECT t.id, t.link, t.data, <emphasis>path || t.id</emphasis>
    FROM tree t, search_tree st
    WHERE t.id = st.link
)
SELECT * FROM search_tree <emphasis>ORDER BY path</emphasis>;
</programlisting>
   </para>

   <para>
    In the general case where more than one field needs to be used to identify
    a row, use an array of rows.  For example, if we needed to track fields
    <structfield>f1</structfield> and <structfield>f2</structfield>:

<programlisting>
WITH RECURSIVE search_tree(id, link, data, <emphasis>path</emphasis>) AS (
    SELECT t.id, t.link, t.data, <emphasis>ARRAY[ROW(t.f1, t.f2)]</emphasis>
    FROM tree t
  UNION ALL
    SELECT t.id, t.link, t.data, <emphasis>path || ROW(t.f1, t.f2)</emphasis>
    FROM tree t, search_tree st
    WHERE t.id = st.link
)
SELECT * FROM search_tree <emphasis>ORDER BY path</emphasis>;
</programlisting>
   </para>

   <tip>
    <para>
     Omit the <literal>ROW()</literal> syntax in the common case where only one
     field needs to be tracked.  This allows a simple array rather than a
     composite-type array to be used, gaining efficiency.
    </para>
   </tip>

   <para>
    To create a breadth-first order, you can add a column that tracks the depth
    of the search, for example:

<programlisting>
WITH RECURSIVE search_tree(id, link, data, <emphasis>depth</emphasis>) AS (
    SELECT t.id, t.link, t.data, <emphasis>0</emphasis>
    FROM tree t
  UNION ALL
    SELECT t.id, t.link, t.data, <emphasis>depth + 1</emphasis>
    FROM tree t, search_tree st
    WHERE t.id = st.link
)
SELECT * FROM search_tree <emphasis>ORDER BY depth</emphasis>;
</programlisting>

    To get a stable sort, add data columns as secondary sorting columns.
   </para>

   <tip>
    <para>
     The recursive query evaluation algorithm produces its output in
     breadth-first search order.  However, this is an implementation detail and
     it is perhaps unsound to rely on it.  The order of the rows within each
     level is certainly undefined, so some explicit ordering might be desired
     in any case.
    </para>
   </tip>

   <para>
    There is built-in syntax to compute a depth- or breadth-first sort column.
    For example:

<programlisting>
WITH RECURSIVE search_tree(id, link, data) AS (
    SELECT t.id, t.link, t.data
    FROM tree t
  UNION ALL
    SELECT t.id, t.link, t.data
    FROM tree t, search_tree st
    WHERE t.id = st.link
) <emphasis>SEARCH DEPTH FIRST BY id SET ordercol</emphasis>
SELECT * FROM search_tree ORDER BY ordercol;

WITH RECURSIVE search_tree(id, link, data) AS (
    SELECT t.id, t.link, t.data
    FROM tree t
  UNION ALL
    SELECT t.id, t.link, t.data
    FROM tree t, search_tree st
    WHERE t.id = st.link
) <emphasis>SEARCH BREADTH FIRST BY id SET ordercol</emphasis>
SELECT * FROM search_tree ORDER BY ordercol;
</programlisting>
    This syntax is internally expanded to something similar

Title: Depth-First and Breadth-First Ordering in SQL Recursive Queries
Summary
This section explains how to implement depth-first and breadth-first ordering in SQL recursive queries. For depth-first ordering, it demonstrates adding a 'path' column to track visited rows, using arrays or composite types. For breadth-first ordering, it shows how to add a 'depth' column. The text provides SQL examples for both approaches, including cases where multiple fields need to be tracked. It also introduces built-in syntax for computing depth-first or breadth-first sort columns using 'SEARCH DEPTH FIRST BY' and 'SEARCH BREADTH FIRST BY' clauses. The section emphasizes that while these methods don't control query evaluation order, they provide a convenient way to sort results afterwards. Tips are included for optimizing performance and ensuring stable sorting.