Consider the following schema:
create table TableA (A1 int)
create table TableB (B1 int, B2 int)
create table TableC (C1 int, C2 int)
create table TableD (D1 int)
And the following query:
SELECT *
FROM TableA a
INNER JOIN TableB b ON b.B1=a.A1
INNER JOIN (SELECT TOP 1 *
FROM TableC c
WHERE c.C1=b.B1 ORDER BY c.C2) foo ON foo.C1=a.A1
INNER JOIN TableD d ON d.D1=foo.C1
In SQL Fiddle (SQL Server 2008) I get the following result:
The multi-part identifier "b.B1" could not be bound.: SELECT * FROM TableA a INNER JOIN TableB b ON b.B1=a.A1 INNER JOIN (SELECT TOP 1 * FROM TableC c WHERE c.C1=b.B1 ORDER BY c.C2) foo ON foo.C1=a.A1 INNER JOIN TableD d ON d.D1=foo.C1
But replacing the INNER JOIN of the subquery by CROSS APPLY fixes the issue:
SELECT *
FROM TableA a
INNER JOIN TableB b ON b.B1=a.A1
CROSS APPLY (SELECT TOP 1 *
FROM TableC c
WHERE c.C1=b.B1 AND c.C1=a.A1 ORDER BY c.C2) foo
INNER JOIN TableD d ON d.D1=foo.C1
My questions are:
1) Why the first query fail?
2) Why the second query doesn’t fail?
3) CROSS APPLY is specific to SQL Server. Which would be the SQL Standard solution to this problem?
Important note: Don’t try to understand the logic behind TableA, …, TableD. They’re just an abstraction to a more complex query (which is awful to read). I think you’ll get the idea of the issue.
Correlated subqueries are not allowed in
fromclauses. That is why theinner joinversion does not work. I don’t actually know the history of this. One problem is that you could get cycles in the dependencies, which while not hard to detect, make the query impossible to process.Your query with
cross applyis one case wherecross applyfits well. However, I don’t know how well it executes on large data.Here is an attempt to rewrite it in standard SQL: