您不能(不应)将非聚合放在SELECT
查询的GROUP BY
行中。
但我想访问与max相关联的非聚合之一。用简单的英语,我想要一张每种类型最老的表。
CREATE TABLE stuff (
id int,
kind int,
age int
);
此查询为我提供了以下信息:
SELECT kind, MAX(age)
FROM stuff
GROUP BY kind;
但它不是最有用的形式。我真的希望与每行关联id
,以便我可以在以后的查询中使用它。
我正在寻找类似的东西:
SELECT id, kind, MAX(age)
FROM stuff
GROUP BY kind;
输出这个:
SELECT stuff.*
FROM
stuff,
( SELECT kind, MAX(age)
FROM stuff
GROUP BY kind) maxes
WHERE
stuff.kind = maxes.kind AND
stuff.age = maxes.age
看起来似乎应该离开以获取此信息而无需加入。我只需要SQL引擎在计算最大值时记住其他列。
答案 0 :(得分:12)
您无法获取MAX找到的行的ID,因为可能不会只有一个ID具有最大年龄。
答案 1 :(得分:6)
您不能(不应该)将非聚合放在GROUP BY查询的SELECT行中。
您可以而且必须定义要为聚合函数分组的内容以返回正确的结果。
MySQL(和SQLite)以无限的智慧决定他们会违反规范,并允许查询接受SELECT BY子句缺少SELECT中引用的列 - 它有效地使这些查询不可移植。
看起来似乎应该离开以获取此信息而无需加入。
如果无法访问MySQL不支持的分析/排名/窗口函数,自联接到派生表/内联视图是获取所需结果的最便携方式。
答案 2 :(得分:2)
我认为确实要求系统在一次通过中解决问题而不是两次完成工作(找到最大值,并找到相应的id)是很诱人的。你可以使用CONCAT(正如Naktibalda提到的文章中所建议的那样),不确定会更有效
SELECT MAX( CONCAT( LPAD(age, 10, '0'), '-', id)
FROM STUFF1
GROUP BY kind;
应该有效,你必须分开答案才能获得年龄和身份证明。 (虽然这真的很难看)
答案 3 :(得分:2)
在最近的数据库中,你可以使用sum()over(partition by ...)来解决这个问题:
select id, kind, age as max_age from (
select id, kind, age, max(age) over (partition by kind) as mage
from table)
where age = mage
这可以是单程
答案 4 :(得分:1)
您必须有一个连接,因为聚合函数max检索许多行并选择最大值。 所以你需要一个联接来选择agregate函数找到的那个。
换句话说,如果用sum替换max,你会期望查询的行为是什么?
内部联接可能比您的子查询更有效。
答案 5 :(得分:0)
PostgesSQL的DISTINCT ON将在此处有用。
SELECT DISTINCT ON (kind) kind, id, age
FROM stuff
ORDER BY kind, age DESC;
这按种类分组并以有序格式返回第一行。当我们按年龄降序排列时,我们将获得具有最大年龄的行。
P.S。 DISTINCT ON中的列应按以下顺序依次显示