复杂的SQL查询,需要根据时间限制通过count排序
Posted
技术标签:
【中文标题】复杂的SQL查询,需要根据时间限制通过count排序【英文标题】:Complex SQL query, need to sort via count based upon time constraints 【发布时间】:2011-04-13 06:16:53 【问题描述】:大家好,我这里有以下三个表格。
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
它可以工作,但执行起来需要很长时间 - 再加上考虑到我的 airports 表有超过 30'000 个条目,并且 trips 表是可变的。
我只是从国家/地区表中获取国家/地区名称 - 如果我在 sql 中排除加入国家/地区表,而是从索引为 ID 的数组中检索国家/地区名称会更好吗和 values 是国家的名称?
【问题讨论】:
【参考方案1】:我不确定您为什么要使用左连接。如果每次旅行都有一个机场,每个机场都有一个国家,那么内部连接将为您提供准确的结果。
我会这样做:
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 列将是另一个重要的索引。但是,如果您打算按“机场名称”搜索,请在此处添加索引。我想你看到了它的发展方向,等等。
【讨论】:
问题是机场的航班不需要条目 - 以这种方式使用内部 JOIN 与航班仅返回那些在航班表中有相应条目的机场 - 我需要计算所有机场的现有航班,无论是零到等等。 这是有道理的。左外连接应该可以工作。之后,索引,查询应该非常快。您会看到性能上的显着差异。【参考方案2】:airpoirt(countryid, id)
和 trips(airportid)
上的索引似乎是最重要的。
而不是count(f.id)
尝试count(f.airportid)
,这样mysql 就不必检查trips.id
列。
【讨论】:
这加快了速度,谢谢 - 但是我需要检索特定时期之间的航班数量。如果在一段时间后设置了航班,则使用 where 子句返回元组以上是关于复杂的SQL查询,需要根据时间限制通过count排序的主要内容,如果未能解决你的问题,请参考以下文章