2013-03-06 66 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 

当然,它很可能最终会被更有效地对表相应的索引并做多个索引扫描。不知道你的数据,很难知道。