A common table expression (CTE) is a named temporary result set that exists within the scope of a single statement and that can be referred to later within that statement, possibly multiple times.

1 With

This tag allows you to do WITH ... AS operations independent of the DBMS.

<with recursive='true|false'>
    <as
        name='name'
        params='params'
    > +
        <select /> *
        <union /> *
    </as>
</with>
Example
Copy
<with>
	<as name="cte1">
		<select>
			<columns>
				a1
			</columns>
			<from table="master_table"/>
		</select>
	</as>
	<select>
		<columns>
			a1
		</columns>
		<from table="cte1"/>
	</select>
</with>
Copy
WITH cte1 AS 
(
    SELECT a1
    FROM master_table
)
SELECT a1 FROM cte1

2 Multiple CTEs

More than one common table expression can be defined to be used in the following statement (select or union).

Example
Copy
<with>
	<as name="cte1">
		<select>
			<columns>
				a1
			</columns>
			<from table="master_table_1"/>
		</select>
	</as>
	<as name="cte2">
		<select>
			<columns>
				a1
			</columns>
			<from table="master_table_2"/>
		</select>
	</as>
	<select>
		<columns>
			cte1.a1
		</columns>
		<from table="cte1">
			<join table="cte2">
				<on>cte1.a1 = cte2.a1</on>
			</join>
		</from>
	</select>
</with>
Copy
WITH cte1 AS 
(
    SELECT a1
    FROM master_table_1
),
cte2 AS 
(
    SELECT a1
    FROM master_table_2
)
SELECT cte1.a1
FROM cte1, cte2
WHERE cte1.a1 = cte2.a1

3 Recursivity

Recursivity can also be used with common table expressions. If there is any recursive CTE, recursive must be set to true in the with tag, and the parameters must be set in params in the corresponding as tag.

Example
Copy
<with recursive="true">
	<as name="cte1" params="n, fact">
		<union>
			<select-one>
				<columns>
					0, 1
				</columns>
			</select-one>
			<select>
				<columns>
					n+1,
					(n+1)*fact
				</columns>
				<from table="cte1"/>
				<where>n &lt; 9</where>
			</select>
		</union>
	</as>
	<select>
		<columns>
			n, fact
		</columns>
		<from table="cte1"/>
	</select>
</with>
Copy
WITH cte1(n, fact) AS 
(
    SELECT 0, 1
    FROM systables
    WHERE tabname = 'systables' 
    UNION  ALL 
    SELECT n+1, (n+1)*fact
    FROM cte1
    WHERE n < 9
)
SELECT n, fact
FROM cte1
+-----------+-----------+
|n          |fact       |
|decimal(11,|decimal(21,|
|0)         |0)         |
+-----------+-----------+
|0          |1          |
|1          |1          |
|2          |2          |
|3          |6          |
|4          |24         |
|5          |120        |
|6          |720        |
|7          |5.040      |
|8          |40.320     |
|9          |362.880    |
+-----------+-----------+

4 Multiple and recursive

Multiple CTEs, some of them being recursive, can also be created.

Example
Copy
<with recursive="true">
	<as name="cte1" params="n, fact">
		<union>
			<select-one>
				<columns>
					0, 1
				</columns>
			</select-one>
			<select>
				<columns>
					n+1,
					(n+1)*fact
				</columns>
				<from table="cte1"/>
				<where>n &lt; 9</where>
			</select>
		</union>
	</as>
	<as name="cte2">
		<select>
			<columns>
				a1
			</columns>
			<from table="master_table"/>
		</select>
	</as>
	<select>
		<columns>
			a1, n, fact
		</columns>
		<from table="cte1, cte2"/>
	</select>
</with>
Copy
WITH cte1(n, fact) AS 
(
    SELECT 0, 1
    FROM systables
    WHERE tabname = 'systables' 
    UNION  ALL 
    SELECT n+1, (n+1)*fact
    FROM cte1
    WHERE n < 9
)
, cte2 AS 
(
    SELECT a1
    FROM master_table
)
SELECT a1, n, fact
FROM cte1, cte2

5 Usefulness example

One of the biggest advantages of CTEs is to avoid code duplication, thus making the code more readable. In the following example the repetition of the CASE WHEN is avoided.

Example
Copy
<with>
    <as>    
        <select>
            <column>
                film_id, 
                title,
                (CASE 
                    WHEN length &lt; 30 THEN 'Short'
                    WHEN length &lt; 90 THEN 'Medium'
                    ELSE 'Long'
                END) length    
            </column>
            <from table="film"/>
        </select>
    </as>
    <select>
        <column>
            film_id,
            title,
            length
        </column>
        <from table="cte_film"/>
    </select>
</with>
Copy
WITH  AS 
(
    SELECT 
        film_id, 
        title,
        (CASE 
            WHEN length < 30 THEN 'Short'
            WHEN length < 90 THEN 'Medium'
            ELSE 'Long'
        END) length    
    FROM film
)
SELECT 
    film_id,
    title,
    length
FROM cte_film
WHERE length = 'Long'