复杂的SQL查询,需要根据时间限制对计数进行排序

时间:2011-04-13 06:16:53

标签: php mysql sql sql-optimization

大家好,我这里有以下三张桌子。

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的数组中检索国家/地区名称会更好吗?和值是国家的名称?

2 个答案:

答案 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列。