2013-03-06 39 views
1

以下查詢工作,但沒有特別快:如何改進此查詢?

select distinct controlid, (
       select max(Orderno) From my_table 
       Where ControlID = #param1# 
        and a = 3 and b = 13 and c = 0 and d = 0 
      ) colA, (
       Select max(Orderno) From my_table 
       Where ControlID = #param1# 
        and a = 2 
      ) colB, (
       Select max(Orderno) From my_table 
       Where ControlID = #param1# 
        and a = 1 and b = 14 and e = 1 
      ) colC, (
       Select max(Orderno) From my_table 
       Where ControlID = #param1# 
        and a = 3 and b = 13 and e = 1 and c = 0 and d = 0 
      ) colD, (
       Select a From my_table 
       Where ControlID = #param1# 
        and Orderno = #param2# 
      ) colE 
      from my_table 
      where controlid = #param1# 

被查詢該表具有超過300K行,並且行的特定控件ID(distinct子句前)計從1變化到61。分析器說響應時間是234/42毫秒。表格中沒有索引。

很顯然,缺乏索引是一個問題,但除此之外,任何人都可以推薦一種更有效的方式來編寫這個查詢嗎?

回答

4

使用聚合而不是子查詢:

select distinct controlid, 
    max (case when a=3 and b=13 and c=0 and d= 0 then OrderNo end) as colA, 
    max (case when a=2       then OrderNo end) as colB, 
    max (case when a=1 and b=14 and e=1   then OrderNo end) as colC, 
    max (case when a=3 and b=13 and e=1 and c=0 and d=0 then OrderNo end) as colD, 
    max (case when OrderNo=#param2# then a end) as colE 
from my_table 
where controlid = #param1# 
group by controlid 

我不知道哪個RDBMS使用,所以case when結構可能需要進行修改,以當地的方言。這一個應該是有效的MSSQL

更新:我的眼鏡不能正常工作,所以我沒有注意到ORACLE標記。尷尬......

+0

可能是oracle,由於標籤..? – Mithon 2013-03-06 19:27:39

+0

爲了在子查詢沒有找到任何內容時保持相同的結果,else子句應該在上面爲null。此外,case表達式的默認值爲null,所以'else null'不需要,但有時用於顯示intent。 – 2013-03-06 19:34:47

+0

你是絕對正確的。我會糾正我的嘗試。 – alzaimar 2013-03-06 19:39:21

3

你應該能夠避免撞到桌子多次,做一個表掃描

SELECT controlID, 
     MAX(CASE WHEN a = 3 
        AND b = 13 
        AND c = 0 
        AND d = 0 
       THEN orderNo 
       ELSE NULL 
       END) colA, 
     MAX(CASE WHEN a = 2 
       THEN orderNo 
       ELSE NULL 
       END) colB, 
     MAX(CASE WHEN a = 1 
        AND b = 14 
        AND e = 1 
       THEN orderNo 
       ELSE NULL 
       END) colC, 
     MAX(CASE WHEN a = 3 
        AND b = 13 
        AND e = 1 
        AND c = 0 
        AND d = 0 
       THEN orderNo 
       ELSE NULL 
       END) colD, 
     MAX(CASE WHEN orderNo = #param2# 
       THEN a 
       ELSE NULL 
       END) colE 
    FROM my_table 
WHERE controlId = #param1# 
GROUP BY controlID 

當然,它很可能最終會被更有效地對錶相應的索引並做多個索引掃描。不知道你的數據,很難知道。