2017-04-07 159 views
1

我有三個表:涉及子查詢的SQL Server查詢 - 性能問題

表1: dbo.pc_a21a22 |

batchNbr     Other columns... 
    --------     ---------------- 
     12345 
     12346 
     12347 

表2: dbo.outcome |

passageId     record 
    ----------    --------- 
     00003     200 
     00003      9 
     00004      7 

表3: dbo.passage |

passageId     passageTime  batchNbr 
    ----------    -------------  --------- 
     00001     2015.01.01   12345 
     00002     2016.01.01   12345 
     00003     2017.01.01   12345 
     00004     2018.01.01   12346 

我想要做的:每個batchNbr表1中獲得第一的最新passageTime從表3的相應passageID隨着該passageID,得到相關的行表2和確定是否所有這些行包含記錄200.每個通道Id最多有2個記錄在表2中

執行此操作的最有效方法是什麼?

我已經創建了一個可以工作的查詢,但它非常慢,因此不適合具有數百萬行的表。任何關於如何更改查詢或以其他方式執行的建議?改變表結構不是一種選擇,我只有讀取數據庫的權限。

我目前的解決方案(慢):

SELECT TOP 50000 
    a.batchNbr, 
    CAST (CASE WHEN 200 in (SELECT TOP 2 record FROM dbo.outcome where passageId in (
    SELECT SubqueryResults.passageId From (SELECT Top 1 passageId FROM dbo.passage pass WHERE pass.batchNbr = a.batchNbr ORDER BY passageTime Desc) SubqueryResults 
    ) 
    ) then 1 else 0 end as bit) as KGT_IO_END 

    FROM dbo.pc_a21a22 a 

所需的輸出是:

batchNbr  200present 
--------- ---------- 
12345   1 
12346   0 

回答

3

我建議你使用表連接,而不是子查詢。

select 
    a.*, b.* 
from 
    dbo.table1 a 
join 
    dbo.table2 b on a.id = b.id 
where 
    /*your where clause for filtering*/ 

編輯:

您可以使用此作爲參考Join vs. sub-query

+1

它必須是'選擇*'。 - 而不是'選擇* .a' .....但除此之外:完美的迴應! –

+0

謝謝!爲什麼表現有很大的差異? – AlexGuevara

+0

@marc_s - 謝謝先生!錯過了那一個。 –

1

試試這個

SELECT TOP 50000 a.*, (CASE WHEN b.record = 200 THEN 1 ELSE 0 END) AS 
KGT_IO_END 
FROM dbo.Test1 AS a 
LEFT OUTER JOIN 
(SELECT record, p.batchNbr 
FROM dbo.Test2 AS o 
LEFT OUTER JOIN (SELECT MAX(passageId) AS passageId, batchNbr FROM 
dbo.Test3 GROUP BY batchNbr) AS p ON o.passageId = p.passageId 
) AS b ON a.batchNbr = b.batchNbr; 

MAX子查詢是batchNbr以獲取最新passageId。 但是,例如你不會得到記錄200,因爲200的記錄的passageId是00001,而的batchNbr 12345最新passageId是00003.

我用LEFT OUTER JOIN因爲passageId從表2不再匹配來自表3的最新的passageId中的任何一個。得到的子查詢將不會有記錄到表1的join。因此INNER JOIN不會顯示您的示例數據中的任何記錄。從您的示例數據

輸出:

batchNbr KGT_IO_END 
    12345   0 
    12346   0 
    12347   0 

輸出,如果我們改變記錄200的passageId到00003(最新爲12345)

batchNbr KGT_IO_END 
    12345   1 
    12346   0 
    12347   0 
+0

感謝您的查詢!你是對的通道問題,我沒有看到它,當我鍵入我的例子 - 編輯原始文章。但是你確實得到了我的意圖:-) – AlexGuevara

+0

那麼它對真實記錄有效嗎?讓我知道你是否需要調整。 – CurseStacker

+0

我沒有完全理解爲什麼b.record部分= 200在你的第一行工作,因爲那個passageId有兩條記錄?它不會返回兩個記錄嗎? – AlexGuevara