这里有一个问题。我有一个表
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条件。谁能提出一个更好的解决方案呢?
这是该问题的常见解决方案。每个子查询都可以这样使用索引。
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;
我对此进行了测试,我不得不使用"use index"提示来诱使它使用第二个索引,但是当我这样做时,我得到了这个优化器计划:
*************************** 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
我想你可以使用这个查询:
-- 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