如何在MySQL中使用MAX?

时间:2011-10-04 22:26:39

标签: mysql

假设以下表格/数据:

person_id  age  gender  name
1          25   Female  Jane
2          28   Male    John
3          29   Female  Jill
4          24   Male    Jack

如何查询最年长的男性和女性?

这不起作用:SELECT person_id, max(age), gender, name FROM person GROUP BY gender

返回:

person_id  age  gender  name
2          28   Male    John
1          29   Female  Jane

期望的结果是:

person_id  age  gender  name
2          28   Male    John
3          29   Female  Jill

我的SQL出了什么问题?

4 个答案:

答案 0 :(得分:3)

当您按GROUP BY性别时,您无法控制为非聚合列选择每个组中的哪个值(age已汇总,但name不是):

来自the docs

MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause.... The server is free
to choose any value from each group, so unless they are the same, the values
chosen are indeterminate.

然而,可以通过子选择获得所需的结果:

SELECT p1.*
FROM person p1
INNER JOIN (
    SELECT gender,MAX(age) as age
    FROM person 
    GROUP BY gender) as p2
ON p1.gender = p2.gender AND p1.age = p2.age

答案 1 :(得分:3)

您可以获取包含ORDER BYLIMIT 1的行的所有数据。在您的情况下,使用此两次并与UNION结合使用:

  ( SELECT * 
    FROM person 
    WHERE gender = 'Male'
    ORDER BY age DESC
    LIMIT 1
  )
UNION ALL
  ( SELECT * 
    FROM person 
    WHERE gender = 'Female'
    ORDER BY age DESC
    LIMIT 1
  )

另一种方法是确定男性和女性的最大年龄(使用子查询):

SELECT *
FROM person
WHERE ( gender = 'Male'
      AND age =  
          ( SELECT MAX(age) 
            FROM person 
            WHERE gender = 'Male'
          )
      )
   OR ( gender = 'Female'
      AND age =  
          ( SELECT MAX(age) 
            FROM person 
            WHERE gender = 'Female'
          )
      )

如果您有两个以上的性别,或者您不想在查询中对MaleFemale常量进行硬编码,则可以将其重写为:

SELECT p.*
FROM person AS p
  JOIN
      ( SELECT gender
             , MAX(age) AS maxage 
        FROM person 
        GROUP BY gender
      ) AS pg
    ON  pg.gender = p.gender
    AND pg.maxage = p.age

上述查询有一个主要区别。第一个将只给你一个男性和一个女性结果(最多)。当有许多(男性)具有相同的最大年龄时,第二个和第三个查询将为您提供多个,对于女性来说也是如此。

(gender, age)上的索引有助于查询。

答案 2 :(得分:1)

您需要先添加ORDER BY age DESC,因为分组会将第一个元素传递给。{/ p>

(我认为你甚至可以用max(age)替换age

答案 3 :(得分:0)

你在评论中说:

By the way, the example I gave is a simplified version of my problem. The real
problem is that I have a certain entity in my database that makes log entries. I
need to find the very last log entry for that entity. I have a timestamp column
in the table

尝试以下方法,应该在我想象中的表格中工作......但是提供表格结构会有所帮助,也可以通过一组来解决:)

select * from log_table
where log_date_time = (select max(log_date_time) from log_table)