0

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

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 条件。任何人都可以提出一个更好的解决方案,它也有利于性能

4

2 回答 2

2

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
于 2012-12-24T17:58:03.953 回答
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
于 2012-12-24T18:08:19.090 回答