Sql-Server

在 select blah where blah IN (SELECT MIN(blah) 中優化 sql server MIN

  • July 7, 2016

有什麼有效的方法來調整下面的查詢嗎?

我在 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 &lt;&gt; 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 &lt;&gt; 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 &lt;&gt; 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 &lt;&gt; 0


   -- query 3
   SELECT OrganisationID, MIN(ID) 
FROM #t T 
WHERE OrganisationID &lt;&gt; 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 &lt;&gt; 0
) tt 
where tt.rn = 1

引用自:https://dba.stackexchange.com/questions/143018