提高查询效率 - 减少全表扫描?

时间:2015-05-29 14:13:15

标签: sql oracle oracle10g

我想知道你是否可以帮助我,我目前有一个工作查询,但我觉得它没有那么高效。我继续解释:

我有一张汽车餐桌和一张carEvent餐桌。车载表只存储汽车的品牌,型号等信息。 CarEvent表存储发生在汽车上的事件,例如汽车已经坠毁或汽车已经修好。如果给定汽车的carEvent表上没有“CRASHED”状态,那么它就没有崩溃。我的查询的作用是返回所有已经崩溃但未修复的汽车。我编写它的方式需要对carEvent表进行两次扫描。

我想知道的是,有更有效的方法来进行此查询吗?

我的查询如下:

SELECT * 
FROM Car c 
WHERE (select count(ce.id) FROM CarEvent ce
       where car_id = c.id AND ce.carEventType = 'CRASHED') > 0 
  AND (select count(ce.id) FROM CarEvent ce
       where car_id = c.id AND ce.carEventType = 'FIXED') = 0 

非常感谢任何建议。

3 个答案:

答案 0 :(得分:2)

哦,子查询中臭名昭着的count()。您想使用exists,而不是count

SELECT c.* 
FROM Car c 
WHERE EXISTS (select 1 FROM CarEvent ce where ce.car_id = c.id AND ce.carEventType = 'CRASHED') AND
      NOT EXISTS (select 1 FROM CarEvent ce where ce.car_id = c.id AND ce.carEventType = 'FIXED');

对于性能,您需要CarEvent(car_id, carEventType)上的索引。另外,尤其要确保在相关子查询中使用表别名。

答案 1 :(得分:1)

使用EXISTSNOT EXISTS

SELECT *  FROM Car c
WHERE EXISTS (select 1 FROM CarEvent ce
              where car_id = c.id AND ce.carEventType = 'CRASHED')
  AND NOT EXISTS (select 1 FROM CarEvent ce
                  where car_id = c.id AND ce.carEventType = 'FIXED')

答案 2 :(得分:1)

使用GROUP BYHAVING,联接数量可以从两个减少到一个:

select Car.id
from Car
join CarEvent on Car.id = CarEvent.car_id
group by Car.id
having
    sum(case when carEventType = 'CRASHED' then 1 else 0 end) > 0
    and
    sum(case when carEventType = 'FIXED' then 1 else 0 end) = 0