Mister Equis
Mister Equis

Reputation: 141

Reuse of a field from a joined table inside a subquery in FROM clause

The following query is not the one I'm using really, but my problem can be replicated in this simpler one. Basically, what I want to do is use or reference a field from a joined table inside a subquery that is in a FROM clause like so.

SELECT t1.field1, t1.field2 - IIF(t3.calcfield is null, 0, t3.calc)
FROM
  (SELECT t2.fieldid, SUM(t2.field3) AS fsum
   FROM t2
   WHERE t2.date > t4.date 
   GROUP BY t2.fieldid) t3
LEFT JOIN
  table4 t4 ON t3.fieldid = t4.fieldid

The field that I need to use is t4.date to make the date comparison inside the subquery but when I execute the query I get the popup window or prompt to enter a value in t4.date.

I just wanted to make that comparison for filtering, so that I can use fsum field in the outer SELECT statement. I think the query is pretty simple to understand in terms of what I want to achieve.

Even though my query is more complex, I replicated the problem with a simple query like this or even simpler.

I tried replicating it in an AQL sandbox webpage: https://sqltest.net/. Tables generated by the sandbox, and in the upper right corner I selected the Oracle database.

Tables:

CREATE TABLE sql_test_a 
( 
    ID         VARCHAR2(4000 BYTE), 
    FIRST_NAME VARCHAR2(200 BYTE), 
    LAST_NAME  VARCHAR2(200 BYTE) 
); 

CREATE TABLE sql_test_b 
( 
    ID         VARCHAR2(4000 BYTE) 
); 

INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('1', 'John', 'Snow'); 
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('2', 'Mike', 'Tyson'); 
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('3', 'Bill', 'Keaton'); 
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('4', 'Greg', 'Mercury'); 
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('5', 'Steve', 'Jobs'); 
INSERT INTO sql_test_a (ID, FIRST_NAME, LAST_NAME) VALUES ('6', 'Johhny', 'Depp');

The SQL code I wrote is the following:

SELECT T1.ID, TINNER.FIRST_NAME
FROM 
  (SELECT T2.ID FROM sql_test_b T2
   WHERE T1.FIRST_NAME LIKE 'greg') TINNER
INNER JOIN
  sql_test_a T1 ON t1.ID = TINNER.ID;

I practically get the same error or problem that consists in that the T1 fields did not exist for the inner subquery or TINNER table.

I'm using Microsoft Access 2003. (simply cause I had it previously).

Upvotes: 1

Views: 2392

Answers (1)

Parfait
Parfait

Reputation: 107687

Recall SQL's logical order of operations that differ from its lexical order (i.e., order in how it is written). Usually the first step in query processing is the FROM clause, then JOIN, ON, WHERE, GROUP BY, etc. and usually ending with ORDER BY and SELECT (ironically one of the last clauses processed though written first).

Technically, your queries do not involve correlated subqueries since there are no inner or outer levels. Specifically, the derived table t3 and base table t4 are at the same level. The query engine evaluates t3 in isolation by itself during FROM clause step. Then, it evaluates JOIN table, t4, in isolation by itself and finally applies the matching ON logic.

Because t4 is not defined in the universe of t3, MS Access via GUI prompts for that parameter value (where MS Access via ODBC will raise an error). To resolve you have to include all necessary data sources in each table scope:

SELECT t1.field1, t1.field2 - IIF(t3.calcfield IS NULL, 0, t3.calc) As Diff
FROM
  (SELECT t2.fieldid, SUM(t2.field3) AS fsum
   FROM t2
   INNER JOIN table4 sub_t4
     ON t2.fieldid = sub_t4.fieldid
   WHERE t2.date > sub_t4.date 
   GROUP BY t2.fieldid
  ) t3
LEFT JOIN table4 t4 
  ON t3.fieldid = t4.fieldid

Often, too, using layered queries is beneficial in Access and can help with final, compact queries:

t3 query (save below as a query object)

SELECT t2.fieldid, SUM(t2.field3) AS fsum
FROM t2
INNER JOIN table4 sub_t4
   ON t2.fieldid = sub_t4.fieldid
WHERE t2.date > sub_t4.date 
GROUP BY t2.fieldid

Final query (join saved query)

SELECT t1.field1, t1.field2 - IIF(t3.calcfield IS NULL, 0, t3.calc) As Diff
FROM my_saved_query t3
LEFT JOIN table4 t4 
   ON t3.fieldid = t4.fieldid

Upvotes: 1

Related Questions