为什么包含聚合的 SQL SELECT 不能访问其他列?

Why can't an SQL SELECT that includes an aggregate access other columns?

我有一份关于商业航空公司航班的 table 信息,其中包括给定航班的出发城市 (origin_city) 和飞行时间 (actual_time).

我试图理解为什么(也许天真)简单的查询没有return飞行时间最长的航班的始发城市。

以下查询:

SELECT FLIGHTS.origin_city, MAX( FLIGHTS.actual_time ) as [time]
FROM FLIGHTS

导致错误:

Column 'FLIGHTS.origin_city' is invalid in the select list because
it is not contained in either an aggregate function or the GROUP BY
clause.

我认为 SQL 解释此查询的方式是它会找到具有最长飞行时间的行,然后显示 origin_cityactual_time 列对于那一行。

为什么那行不通?

如果我将 origin_city 排除在 SELECT 之外,则查询运行正常:

SELECT MAX( FLIGHTS.actual_time ) as [time]
FROM FLIGHTS

如果我按 origin_city 对航班进行分组,那么 SQL 从每一行中提取 origin_cityactual_time 都没有任何问题。

SELECT FLIGHTS.origin_city, MAX( FLIGHTS.actual_time ) as [time]
FROM FLIGHTS
GROUP BY FLIGHTS.origin_city

请注意,我不是在寻找有效的查询;我试图理解为什么我在 post 开头的幼稚查询不起作用。 . . :-P

这看起来似乎有一个简单的答案......但是......关于为什么你的第一个查询不能给你你想要的东西的简单答案是你从未告诉它在FLIGHTS.origin_city 所以它不知道如何处理该字段。您添加了 MAX 的聚合函数,但您还添加了另一个字段...所以现在它不仅查看 FLIGHTS.actual_time,而且查看 FLIGHTS.origin_city,所以现在当我们对 FLIGHTS.origin_city 进行分组时,查询知道您希望看到每个 origin_city.

的 MAX actual_time

查询不知道您需要哪个城市的 MAX(FLIGHTS.actual_time)。如果你想知道一个特定的 origin_city 和它的 MAX actual_time 你可以在 WHERE 子句中添加一个过滤器来指定你想看到哪个 origin_city ...否则通过添加 origin_city 到 GROUP BY 子句,这现在告诉查询您希望看到每个城市的 MAX actual_time。

如果不添加到 GROUP BY 子句中 SQL 不知道如何使用 MAX。

SELECT FLIGHTS.origin_city, MAX( FLIGHTS.actual_time ) as [time]
FROM FLIGHTS

The way I would think that SQL would interpret this query is that it would find the row that has the maximum flight time and then display the origin_city and the actual_time columns for that row.

我觉得这种解释很愚蠢。您建议 SQL 如何处理这些查询?

SELECT FLIGHTS.origin_city, MAX(FLIGHTS.actual_time) as [time],
       MIN(FLIGHTS.actual_time)
FROM FLIGHTS;

或者:

SELECT FLIGHTS.origin_city, AVG(FLIGHTS.actual_time) as [time]
FROM FLIGHTS;

没那么明显吧?我想如果有一个聚合函数并且它是 MIN()MAX() 而不是任何其他聚合函数,您可以做出一些“特例”解释。事实上,SQLite 就是这么做的——这对通过该数据库学习聚合的人不利。

此外,还有一个真正简单的方法来做你想做的事:

SELECT FLIGHTS.origin_city, FLIGHTS.actual_time
FROM FLIGHTS
ORDER BY FLIGHTS.actual_time DESC
OFFSET 0 ROW FETCH FIRST 1 ROW ONLY;