日期范围内的记录 - 性能

时间:2012-12-24 17:52:19

标签: mysql sql date

这是一个问题。我有一张桌子

flightdetails
-----------+-------------
flightName | varchar(200)
departure  | date
arrival    | date

我希望获得指定日期范围内的所有航班。 fromDate或toDate应该在给定的日期范围内。我知道一个简单的查询,它会给我结果

select flightname from flightdetails where (departure between fromDate and toDate)
or (arrival between fromDate and toDate);

但是这对性能不利,因为我使用OR条件。任何人都可以建议一个更有利于性能的更好的解决方案

2 个答案:

答案 0 :(得分:2)

这是此问题的常见解决方案。每个子查询都可以通过这种方式使用索引。

select flightname from flightdetails where departure between fromDate and toDate
union
select flightname from flightdetails where arrival between fromDate and toDate;

来自@SalmanA的评论

你是对的,上面的查询错过了这样的案例:

departure < fromDate < toDate < arrival

由于出发地和抵达都不在日期范围之间,但当然日期范围包含在航班时间内。

这是另一个基于你的解决方案,但它在出发和到达时都使用了索引。确保为每个条件创建复合索引:

create index flt_d on flightdetails(flightname, departure);
create index flt_a on flightdetails(flightname, arrival);

select f1.flightname 
from flightdetails f1
join flightdetails f2 use index (flt_a)
  on f1.flightname = f2.flightname
where f1.departure <= toDate
  and f2.arrival >= fromDate;

我测试了这个,我不得不使用&#34;使用索引&#34;提示哄它使用第二个索引,但是当我这样做时,我得到了这个优化器计划:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: f1
         type: index
possible_keys: flt_d,flt_a
          key: flt_d
      key_len: 20
          ref: NULL
         rows: 3
        Extra: Using where; Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: f2
         type: ref
possible_keys: flt_a
          key: flt_a
      key_len: 12
          ref: test.f1.flightname
         rows: 1
        Extra: Using where; Using index

答案 1 :(得分:1)

我认为您可以使用此查询:

-- 2.2) select date ranges that overlap [d1, d2] (d2 and end_date are inclusive)  
SELECT * FROM <table> WHERE @d2 >= start_date AND end_date >= @d1

进行少量替换,例如start_date变为出发,end_date变为到达等等:

SELECT flightname
FROM   flightdetails
WHERE  toDate >= departure AND arrival >= fromDate