Sql-Server
在 select blah where blah IN (SELECT MIN(blah) 中優化 sql server MIN
有什麼有效的方法來調整下面的查詢嗎?
我在 OrganisationID <> 0 上有一個過濾索引,主鍵在另一個欄位上,與此查詢 ItemCode varchar(20) 無關。
我標記了 sql server 2005 因為它需要在那里工作,但是如果在任何其他 sql server 版本中還有其他內容,請提出來。
-------------------------------------- -- START CLEAR -------------------------------------- begin try drop table #T end try begin catch end catch -------------------------------------- -- THE TABLE -------------------------------------- CREATE TABLE #T ( a1 int, a2 int, ID INT, OrganisationID INT, Distance INT, constraint PKt1 PRIMARY KEY CLUSTERED (A1,A2,ID) ) -------------------------------------- -- ADDING SOME DATA -------------------------------------- INSERT INTO #T SELECT 1,1,0,10,100 UNION ALL SELECT 1,1,1,10,200 UNION ALL SELECT 1,1,3,10,50 UNION ALL SELECT 1,1,4,20,80 UNION ALL SELECT 1,2,5,20,300 UNION ALL SELECT 1,2,6,0,100 UNION ALL SELECT 1,3,7,0,100 UNION ALL SELECT 1,3,4,10,100 GO -------------------------------------- -- INDEX CREATION -------------------------------------- create index idx_T_OrganisationID on #T (id) WHERE OrganisationID <> 0 GO -------------------------------------- -- THE QUERY -------------------------------------- --SET STATISTICS IO ON --SET STATISTICS TIME ON SELECT PID.ID, PID.OrganisationID FROM #t AS PID WHERE id IN ( SELECT MIN(id) FROM dbo.#t WHERE OrganisationID <> 0 GROUP BY OrganisationID )
綜合測試後 - 結果
在這 3 個查詢中:
-- query 1 SELECT PID.ID, PID.OrganisationID FROM #t AS PID WHERE id IN ( SELECT MIN(id) FROM dbo.#t WHERE OrganisationID <> 0 GROUP BY OrganisationID ) -- query 2 SELECT rn.ID, --... other columns go here rn.OrganisationID FROM ( SELECT *, n = ROW_NUMBER() OVER(PARTITION BY OrganisationID ORDER BY id) FROM #t ) rn WHERE n= 1 AND OrganisationID <> 0 -- query 3 SELECT OrganisationID, MIN(ID) FROM #t T WHERE OrganisationID <> 0 GROUP BY OrganisationID ;
第一個甚至沒有帶來最正確的結果,查詢 3(如 spaghettidba 和 ypercubeᵀᴹ 在評論中所建議的)是在我的實時環境中性能最好的一個,具有我的真實表和數據,如下所示,我最初的查詢和基於查詢 3 的查詢:
特別是對於這個練習,使用表 #T 查詢 2 和查詢 3 執行更多或更少,根據下面的查詢計劃(圖片):
此查詢通常執行得更好:
SELECT rn.ID, --... other columns go here rn.OrganisationID FROM ( SELECT *, n = ROW_NUMBER() OVER(PARTITION BY OrganisationID ORDER BY id) FROM #t ) rn WHERE n= 1
注意確定它是否會更有效
select * from ( SELECT PID.ID, PID.OrganisationID , row_number() over (partition by PID.OrganisationID order by PID.id) as rn FROM #t AS PID WHERE PID.OrganisationID <> 0 ) tt where tt.rn = 1