简体   繁体   中英

Records within date range - Performance

Here is a problem. I have a table

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

I want to get all the flights in the given date range. Either fromDate or toDate should be inside the given daterange. I know of a simple query which will give me the result

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

But this not good for performance as I use an OR condition. Can anyone suggest a better solution which favours performance too

This is a common solution to this problem. Each subquery can make use of an index this way.

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

Re comment from @SalmanA

You're right, the query above misses cases like this:

departure < fromDate < toDate < arrival

Since neither departure nor arrival are between the date range, but of course the date range is included in the flight time.

Here's another solution, based on yours but it makes use of indexes both on departure and arrival. Be sure to create compound indexes for each condition:

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;

I tested this out and I had to use the "use index" hint to coax it to use the second index, but when I did I got this optimizer plan:

*************************** 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

I think you could use this query:

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

Making few substitutions eg start_date becomes departure, end_date becomes arrival, etc:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM