代码之家  ›  专栏  ›  技术社区  ›  deft_code

是否可以将非聚合列与group by一起使用?

  •  16
  • deft_code  · 技术社区  · 16 年前

    你不能(不应该)把非聚合放在 SELECT a线 GROUP BY

    但是,我想访问与最大值相关的非聚合之一。在简单的英语中,我想要一个表,其中包含每种类型中最早的id。

    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 回复  |  直到 7 年前
        1
  •  12
  •   Blorgbeard    16 年前

    无法获取MAX找到的行的Id,因为可能不止一个Id具有最大年龄。

        2
  •  6
  •   urig    7 年前

    不能(不应)将非聚合放在GROUP BY查询的SELECT行中。

    MySQL(和SQLite)以其无穷的智慧决定,它们将违背规范,并允许查询接受GROUPBY子句(SELECT中缺少引用的列),这实际上使这些查询不可移植。

        3
  •  2
  •   mb14    16 年前

    我认为要求系统一次解决问题而不是两次(找到最大值,然后找到相应的id)确实很诱人。您可以使用CONCAT(正如Naktibalda引用的文章中所建议的那样),不确定这是否更有效

    SELECT MAX( CONCAT( LPAD(age, 10, '0'), '-', id)
    FROM STUFF1
    GROUP BY kind;
    

    如果可行的话,你必须把答案分开才能得到年龄和身份证。 (不过那真的很难看)

        4
  •  2
  •   Grimaldi    13 年前

    在最近的数据库中,可以使用sum()over(parition 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
    

        5
  •  1
  •   developer    16 年前

    必须有一个连接,因为聚合函数max检索许多行并选择max。 所以需要一个连接来选择agregate函数找到的连接。

    换言之,如果用sum替换max,您希望查询的行为如何?

    不过,内部连接可能比子查询更有效。

        6
  •  1
  •   Aneesh Dash    8 年前

    SELECT DISTINCT ON (kind) kind, id, age 
    FROM stuff
    ORDER BY kind, age DESC;
    

    这将按种类分组,并以有序格式返回第一行。因为我们已经按年龄降序排列,所以我们将得到kind的最大年龄行。