0

Here is the query in question :

SELECT name, totals1.all_purchases
FROM accounts, 
    (SELECT orders.account_id, SUM(total) AS all_purchases 
    FROM orders 
    GROUP BY orders.account_id) totals1
WHERE accounts.id = totals1.account_id
AND totals1.all_purchases >= 
    ALL (SELECT totals1.all_purchases FROM totals1);

The error text returned is the following:

ERROR:  relation "totals1" does not exist
LINE 8:     ALL (SELECT totals1.all_purchases FROM totals1);

I know I can easily solve this problem using a postgres CTE, and that it would be the better approach. But I want to understand why this code behaves this way, and want someone to point out the flaws in my logic. By the Wikipedia definition of a correlated query:

a correlated subquery (also known as a synchronized subquery) is a subquery (a query nested inside another query) that uses values from the outer query.

because the subquery is correlated with a column of the outer query, it must be re-executed for each row of the result.

My logic is, since a correlated subquery is driven by the outer query, it should execute after the outer query. Therefore this inner query should have no problem recognizing the totals1 table.

For example, this code fails as expected, because when the FROM statement is first executed, the subquery that creates totals1 has not yet been executed.

SELECT name, totals1.all_purchases
FROM accounts, totals1
WHERE accounts.id = totals1.account_id
AND totals1.all_purchases >= 
ALL(SELECT totals1.all_purchases 
   FROM (SELECT orders.account_id, SUM(total) AS all_purchases 
      FROM orders 
      GROUP BY orders.account_id) totals1;

I am also aware of the existence of the LATERAL keyword. I don't think it applies to this situation though, I believe that was meant for correlated subqueries in the outer FROM clause. Case in point I literally used it in every way possible to no avail.

Could this be a possible limitation of PostgreSQL, or is it in the SQL standard altogether ?

PS: here is the schema. You might recognize it from the Udacity's SQL for data analysts course.

6
  • 3
    The query show does not give the error you show. Rather it gives 'ERROR: relation "totals1" does not exist'. Commented Oct 21, 2021 at 1:46
  • Are you just trying to find the account that's spent the most? Commented Oct 21, 2021 at 4:39
  • 1
    @jjanes thank you for pointing this it out, just fixed it. Commented Oct 21, 2021 at 10:22
  • @dwhitemv yeah, but it's not about what I'm doing it's about why I'm doing it. I want to know why this particular subquery returns the error, not an alternative way to get the same result.. Commented Oct 21, 2021 at 10:24
  • 3
    I don't think there is any profound answer. It doesn't work that way because that is not the way it works. The alias assigned to a subquery (yours is uncorrelated, by the way) is just used to qualify column names, not to create a CTE. Commented Oct 21, 2021 at 11:46

1 Answer 1

2

We are allowed to reference the derived table totals1 in the WHERE clause, as you already do but here we are actually referencing a column, not the table as a whole:

WHERE accounts.id = totals1.account_id

But while totals1 is still visible inside the subquery, it is not allowed to use it in a FROM clause.

The only tables allowed to use in a FROM clause are the tables and views of the database (including temporary ones) and any CTE that is visible in that part of the query.

Some explanation can be found in Postgres' documentation about SELECT,
section FROM clause:

FROM Clause

The FROM clause specifies one or more source tables for the SELECT. ...
The FROM clause can contain the following elements:

table_name
The name (optionally schema-qualified) of an existing table or view. (emphasis mine) If ...
with_query_name
A WITH query is referenced by writing its name, just as though the query's name were a table name. ...
...
(other elements omitted)

The SQL standards should have more explicit (and hard to read) details.

2
  • Thank you, that does clear things a lot. Do you know of any resources where I can read about such things ? I could not find any in the postgres documentation. Commented Oct 21, 2021 at 15:33
  • Added some more info. Commented Oct 21, 2021 at 19:12

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.