2011-12-07 45 views
2

我繼承了一個存儲過程執行跨八張桌子,其中一些含有幾百幾千行的連接「連接表中選擇前10名」,然後選擇頂部來自該連接結果的十個條目。「選擇前10名,然後加入表」,而不是

我必須在程序開始足夠的信息來從單一的表中選擇那些十行,然後執行這些加入那些十行,而不是成千上萬的中間排。

我該如何選擇那些十大行,然後只做加入那些十行,而不是執行連接所有的數千行的表中的?

+4

Normalyl的uery優化做到這一點。檢查執行計劃 - 您可能在這裏完全沒有問題。 – TomTom

+0

查詢返回用戶所處理的最後十條記錄。出現這個問題的原因是,從事最多記錄的用戶看到了最糟糕的問題。我會承認,我可能會錯誤地看待問題,但這絕對不是問題 – Frosty840

+0

是的,例如......都是獨立的嗎? – TomTom

回答

7

我應該嘗試:

SELECT * FROM 
    (SELECT TOP 10 * FROM your_table 
    ORDER BY your_condition) p 
INNER JOIN second_table t 
    ON p.field = t.field 
0

你也可以使用一個CTE來定義頂部X,然後用它

例如,這data.se query限制僅將達到40標籤

with top40 as (
    select top 40 t.id, t.tagname 
    from tags t, posttags pt 
    where pt.tagid = t.id 
    group by t.tagname, t.id 
    order by count(pt.postid) desc 
), 

myanswers as(
    select p.parentid, p.score 
    from posts p 
    where 
    p.owneruserid = ##UserID## and 
    p.communityowneddate is null 
) 

select t40.tagname as 'Tag', sum(p1.score) as 'Score', 
case when sum(p1.score) >= 15 then ':-)' else ':-(' end as 'Status' 
from top40 t40, myanswers p1, posttags pt1 
where 
    pt1.postid = p1.parentid and 
    pt1.tagid = t40.id 
group by t40.tagname 
order by sum(p1.score) desc 
+1

這相當於marco的答案; CTE只是嵌套子查詢的更優雅的語法。 (有一些例外,但在這種情況下是這樣)。 –

1
  1. 優化可能不能,如果你有內部執行前10名第一次加入,因爲它不能確保內部聯接稍後不會排除行。如果它從主表中選擇了10行,並且因爲連接而僅在最後返回了7行,那將是一個錯誤。使用Marco的重寫可能會因爲這個原因而獲得性能,因爲您明確指出在連接之前限制行是安全的。
  2. 如果你查詢是足夠複雜,查詢計劃優化器可以運行的時間找到一個很好的計劃。它只有幾百毫秒,並且即使有幾個連接,也可能有成千上萬種不同的方式來執行查詢(不同的連接命令等)。如果是這樣的話,你會從先在一個臨時表中存儲的前10行,然後使用中獲益,後來是這樣的:

    select top 10 * 
    into #MainResults 
    from MyTable 
    order by your_condition; 
    
    
    select * 
    from #MainResults r 
    join othertable t 
        on t.whatever = r.whatever; 
    

    我在哪裏見過這第二種方法已經取得了巨大的情況下,區別。

+1

嗯,我幾乎總是有相反的經歷。將臨時錶轉換爲內聯視圖,CTE或普通舊聯接比臨時表更好 –

+1

完全取決於規模。如果行數很少(在這種情況下是10),這可能是值得的。如果他們開始變得更高,那麼它就不值得。 –