我可以将非聚合列与group by一起使用吗?

时间:2010-07-02 17:59:44

标签: sql mysql group-by aggregate

您不能(不应)将非聚合放在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引擎在计算最大值时记住其他列。

6 个答案:

答案 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中的列应按以下顺序依次显示