2013-02-02 59 views
1

考慮以下方案:內加入VS跨應用 - 多部分組成的標識符無法綁定

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小提琴(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Ø ˚F通過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)爲什麼第二個查詢不會失敗?

3)CROSS APPLY特定於SQL Server。哪一個是這個問題的SQL標準解決方案?

重要注意事項:不要試圖理解TableA,...,TableD背後的邏輯。它們只是一個更復雜查詢的抽象(這很難讀)。我想你會明白這個問題。

回答

3

from子句中不允許使用相關子查詢。這就是爲什麼inner join版本不起作用。我實際上並不知道這個歷史。一個問題是你可能在依賴關係中獲得週期,雖然這些週期不難發現,但卻無法處理查詢。

您的詢問cross applycross apply適合的一種情況。但是,我不知道它在大數據上執行的效果如何。

這裏是重寫它在標準SQL的嘗試:

SELECT * 
FROM TableA a 
INNER JOIN TableB b ON b.B1=a.A1 
INNER JOIN (select * 
      from (select c.*, row_number() over (partition by c1 order by c2) 
        FROM TableC c 
       ) c 
      where seqnum = 1 and foo.C1=a.A1 and c.C1=b.B1 
      ) foo 
INNER JOIN TableD d ON d.D1=foo.C1 
+1

你缺少一個括號和別名:')富安...' –