2015-05-29 56 views
2

我想知道你是否能帮助我,我目前有一个工作查询,但我觉得它并不像它可能是有效的。虐待继续解释:提高我的查询效率 - 减少全表扫描?

我有一个车表和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 

任何意见是极大的赞赏。

回答

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)的索引。另外,特别要确保在相关的子查询中使用表别名。

+0

非常感谢您的答复和对不起我迟到回复。这个答案很完美。感谢还贡献了其他人。 – J145

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') 
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