如何改进这个查询?

时间:2013-03-06 19:18:51

标签: sql oracle

以下查询有效,但速度不是很快:

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行,特定controlid(在distinct子句之前)的行数从1到61不等。分析器表示响应时间为234/42 msecs。桌子上没有索引。

显然,缺少索引是一个问题,但除此之外,是否有人可以推荐一种更有效的方式来编写此查询?

2 个答案:

答案 0 :(得分: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标签。尴尬......

答案 1 :(得分: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

当然,在桌面上拥有适当的索引并进行多次索引扫描可能会更有效率。在不知道您的数据的情况下,很难知道。