假设以下表格/数据:
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出了什么问题?
答案 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 BY
和LIMIT 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'
)
)
如果您有两个以上的性别,或者您不想在查询中对Male
和Female
常量进行硬编码,则可以将其重写为:
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)