SQLite Forum

Subqueries and "no such column" error on references to other tables
Login
Please forgive me, I may not be 100% following your question, and it's very late, but I'll give it a try.

Firstly, I don't know what "exhibits quadratic behavior" means in this case, but I will assume you are asking "will the QP do a Cartesian join where it steps ALL the "FROM rows" (chat) times ALL the JOINed rows (post). [aka O(n^2)]

That answer is no, even though it seems like it would have to.

The Query you propose (for which the Query plan is given) seemingly will start by walking (iterating through) the entire chat table (because you offer no filter in a WHERE clause or such).

Now note that the QP is free to choose to start with the joined table if it pleases, but won't in this case as reported by the query plan.

It then will simply look up the correlated value using the PK (rowid) of the "post" table, causing only O(log n) look-ups. Note that your ORDER BY and DESC LIMIT 1 statements has no effect and is completely ignored here because the link is to a rowid (or stated otherwise, the unique primary key) so row number N can only ever be row number N, no matter how it is "ordered" or limited, in any lookup.

i.e. - this should have the same query plan:
```
EXPLAIN QUERY PLAN
SELECT chat.*, post.* 
FROM chat 
JOIN post ON post.id = (SELECT id FROM post WHERE post.id = chat.id);
```

This may well NOT be the case for other types of correlated sub-query which perhaps do not use the primary key. In that case, the order-by would help to make the QP construct a temporary table with temporary index to do the look-ups. It is hard to guarantee though, and best practice when doing correlated sub-queries is to ensure you have Indexes on the looked-up fields.

I find it best to think of the correlated sub-query as a form of Table/View, and then asking myself if I can see a clear relationship between the tables and how I can phrase the query so the Query-planner cannot miss that same relationship. (And then test it with EXPLAIN of course).

Another way of doing the above would be with a Common Table Expression (CTE - more good reading material) which is like creating a view inside your query which may look something like this:

```
WITH PD AS (
   SELECT id FROM post
)
SELECT chat.*, PD.* 
FROM chat 
JOIN PD ON PD.id = chat.id;
```

which is roughly equivalent to:

```
SELECT chat.*, PD.* 
FROM chat 
JOIN (SELECT id FROM post) AS PD ON PD.id = chat.id;
```

but with the advantage that multiple CTEs can be added and that they can refer each other in their respective SELECT clauses.

This is all tricky, because the Query Planner can decide, based on many whims, how it wants to traverse query tables. It may be that your Query suddenly switches to another plan after adding some data and doing ANALYZE.
The best is to test with some real-World data.

Hope that helps and best of luck!