次のスキーマを検討してください。
create table TableA (A1 int)
create table TableB (B1 int, B2 int)
create table TableC (C1 int, C2 int)
create table TableD (D1 int)
そして、次のクエリ:
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
SQL Fiddle (SQL Server 2008) では、次の結果が得られます。
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
ただし、サブクエリのINNER JOINをCROSS APPLYに置き換えると、問題が修正されます。
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
私の質問は次のとおりです。
1) 最初のクエリが失敗するのはなぜですか?
2) 2 番目のクエリが失敗しないのはなぜですか?
3) CROSS APPLYは SQL Server に固有です。この問題に対する SQL 標準ソリューションはどれですか?
重要な注意: TableA、...、TableD の背後にあるロジックを理解しようとしないでください。それらは、より複雑なクエリの単なる抽象化です (これは読みにくいです)。問題の趣旨はお分かりいただけると思います。