大家好,我这里有以下三张桌子。
COUNTRIES
ID | Name | Details
Airports
ID | NAME | CountryID
Trips
ID | AirportID | Date
我必须检索显示以下内容的列表:
AirportID | AIrport Name | Country Name | Number of Trips Made Between Date1 and Date2
我需要这个非常高效,我需要设置什么样的索引以及如何在此处制定SQL查询?我会用Php显示这个。请注意,我需要能够根据旅行次数进行排序。
编辑==
哎呀忘了提我的sql:
我尝试了以下内容:
SELECT `c`.*, `t`.`country` AS `country_name`, COUNT(f.`id`) AS `num_trips` FROM `airports` AS `c`
LEFT JOIN `countries` AS `t` ON t.`id` = c.`country_id`
LEFT JOIN `trips` AS `f` ON f.`airportid` = c.`id` GROUP BY `c`.`id` ORDER BY `num_flights` ASC LIMIT 10
它可以工作,但执行时间确实太长 - 再考虑一下,我的机场表有超过30,000个条目,并且旅行表是可变的。
我只是从countries表中获取国家/地区的名称 - 如果我要在sql中排除加入teh countries表而不是从索引是ID的数组中检索国家/地区名称会更好吗?和值是国家的名称?
答案 0 :(得分:2)
我不确定你为什么要使用左连接。如果每次旅行都有一个机场,每个机场都有一个国家,内部联接会给你准确的结果。
我会这样做:
select a.ID as AirportID, a.Name as AirportName, c.Name as CountryName, count(t.id) as NumTrips
from Trips t
inner join Airports a on t.AirportID = a.ID
inner join Countries c on a.CountryID = c.ID
where t.Date >= @StartDate
and t.Date <= @EndDate
group by AirportID, AirportName, CountryName
order by NumTrips
limit 10
将@StartDate和@EndDate替换为适当的值。
不确定你在结果中寻找什么,但我希望你想要最多的旅行。在这种情况下,你会想要“按NumTrips desc排序”。这将首先显示最高值,特别是因为您将其限制为10。
另外,我建议您将“日期”列重命名为不会与保留的SQL字冲突的内容。我通常使用“DateCreated”或“DateOfTravel”或类似的东西。
如果我做出任何可怜的假设,请告诉我,我可以重写。
编辑:
对于索引,请在要查找的字段上创建它们。换句话说,主键(应该始终被索引),外键,在这种情况下看起来像Date列将是另一个重要的索引。但是,如果您打算按“机场名称”进行搜索,则在那里添加索引。我想你会看到它的发展方向等等。
答案 1 :(得分:1)
airpoirt(countryid, id)
和trips(airportid)
上的索引似乎是最重要的。
而不是count(f.id)
尝试count(f.airportid)
,因此MySQL不必检查trips.id
列。