Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SQLite's new WITH RECURSIVE CTE clause

SQLite 3.8.3 added support for CTEs. I tried some of the sample CTEs on this page and they work fine. However, after reading the documentation and trying to adapt some of the examples I am unable to create a simple test.

First, I create a simple table with two fields: id and parent. This will create a simple tree or linked list of records:

CREATE TABLE test(id INTEGER PRIMARY KEY ASC,parent INTEGER);

Now I populate it with a few rows:

INSERT INTO test (parent) VALUES (NULL); 
INSERT INTO test (parent) VALUES (1); 
INSERT INTO test (parent) VALUES (2); 
INSERT INTO test (parent) VALUES (3); 

After which I have a table that looks like this:

---+-------
id | parent
---+-------
 1 | NULL
 2 |  1
 3 |  2
 4 |  3

Now I want to generate a list of rows along the path between 3 and 1:

WITH RECURSIVE test1(id,parent) AS (
    VALUES(3,2) 
    UNION ALL 
    SELECT * FROM test WHERE test.parent=test1.id) 
SELECT * FROM test1;

But I get the error:

no such column: test1.id

Both test and test1 have an id field, so why does it claim it does not exist? I have reviewed the documentation several times and don't see my mistake. What am I doing wrong?

like image 839
Michael Avatar asked Jun 17 '14 00:06

Michael


People also ask

When working with recursive CTE which option is used?

You can define the maximum number of recursions for CTE, using the MAXRECURSION option. Set the value of MAXRECURSION to 0, if you don't know the exact numbers of recursions.

Which clause Cannot be used in CTE?

The clauses like ORDER BY, INTO, OPTION clause with query hints, FOR XML, FOR BROWSE, cannot be used in the CTE query definition. "SELECT DISTINCT", GROUP BY, PIVOT, HAVING, Scalar aggregation, TOP, LEFT, RIGHT, OUTER JOIN, and Subqueries are not allowed in the CTE query definition of a recursive member.

Can I use CTE in another CTE?

A CTE name can be referenced in other CTEs, enabling CTEs to be defined based on other CTEs. A CTE can refer to itself to define a recursive CTE. Common applications of recursive CTEs include series generation and traversal of hierarchical or tree-structured data.

How do you do CTE recursion?

Again, at the beginning of your CTE is the WITH clause. However, if you want your CTE to be recursive, then after WITH you write the RECURSIVE keyword. Then it's business as usual: AS is followed by the parentheses with the CTE query definition. This first query definition is called the anchor member.


1 Answers

It is necessary to include the test1 table in the SELECT:

WITH RECURSIVE test1(id,parent) AS (
    VALUES(3,2)
    UNION ALL 
    SELECT test.id,test.parent FROM test,test1 WHERE test1.parent=test.id)
SELECT * FROM test1;

Note that the WHERE clause has been reversed, the original test in the question returns from the current row to the end, rather than from the end back to the start.

like image 127
Michael Avatar answered Oct 06 '22 14:10

Michael