2011-07-18 43 views
0

我想改變我的子查詢到一個連接,它只在子查詢中選擇一條記錄。它似乎運行子查詢每個找到的記錄,接管一分鐘來執行:SQL:將子查詢轉變爲聯接:如何在嵌套聯接的where子句中引用外部表?

select afield1, afield2, (
    select top 1 b.field1 
    from anothertable as b 
    where b.aForeignKey = a.id 
    order by field1 
) as bfield1 
from sometable as a 

如果我儘量只選擇相關的記錄,它不知道如何在嵌套綁定a.id選擇。

select afield1, afield2, bfield1 
from sometable a left join (
    select top 1 id, bfield, aForeignKey 
    from anothertable 
    where anothertable.aForeignKey = a.id 
    order by bfield) b on 
     b.aForeignKey = a.id 
-- Results in the multi-part identifier "a.id" could not be bound 

如果我在嵌套where子句中硬編碼值,選擇時間從60秒降到5秒以下。任何人都有關於如何在不處理內部表中的每條記錄時加入這兩個表的建議?

編輯:

我最終加入

left outer join (
    select *, row_number() over (partition by/order by) as rank) b on 
    b.aforeignkey = a.id and b.rank = 1 

從50秒跑到8 22M行。

回答

2

試試這個:

WITH qry AS 
(
    SELECT afield1, 
      afield2, 
      b.field1 AS bfield1, 
      ROW_NUMBER() OVER(PARTITION BY a.id ORDER BY field1) rn 
     FROM sometable a LEFT JOIN anothertable b 
     ON b.aForeignKey = a.id 
) 
SELECT * 
    FROM qry 
WHERE rn = 1 
+0

這是不是選擇所有的行,然後選擇該行將成爲第一?我會認爲這將與'sometable join(select * from anablertable b)b on a.id = b.aForeignKey'一樣。如果這些相同,查詢從5秒到幾分鐘,但更快比爲每個找到的記錄執行的子查詢。 +1的工作解決方案。也許創建一個表值函數? –

+0

你絕對是在正確的軌道上。如果你想選擇所有的參數,包括像上面那樣的一個rank(row_number),我將你的CTE轉換成一個內聯表值函數,它接受主鍵的參數或者爲它們的空值。現在我可以從dbo.sometablef(/ * aForeignKey */1)中選擇* where rank = 1'。謝謝! –

+0

唯一的問題是TVF參數必須進行硬編碼,所以我製作了TVF,上面列出了你的等級,然後加入rank = 1的地方。工作很好。 –

0

試試這個

select afield1, 
afield2, 
bfield1 
from sometable a 
left join 
(select top 1 id, bfield, aForeignKey from anothertable where aForeignKey in(a.id) order by bfield) b on b.aForeignKey = a.id 
+0

從我發現,在(a.id)給出了不能被綁定相同的錯誤。 –