如何获得包含每个分组集的最大值的行?
我在这个问题上看到过一些过于复杂的变化,没有一个能给出好的答案。我试着把最简单的例子放在一起:
如果有这样一个表,其中有person、group和age列,那么您如何获得每组中最年长的人(一组中的平局应给出第一个按字母顺序排列的结果)
Person | Group | Age
---
Bob | 1 | 32
Jill | 1 | 34
Shawn| 1 | 42
Jake | 2 | 29
Paul | 2 | 36
Laura| 2 | 39
期望结果集:
Shawn | 1 | 42
Laura | 2 | 39
17条答案
按热度按时间zqdjd7g91#
您可以针对一个子查询进行联接,该子查询将
MAX(Group)
以及Age
. 这种方法在大多数rdbms中都是可移植的。50few1ms2#
在mysql中有一种非常简单的方法:
这是因为在mysql中不允许聚合非groupby列,在这种情况下mysql只返回第一行。解决方案是首先对数据进行排序,这样对于每个组,您需要的行是第一个,然后按您需要的值所在的列进行分组。
您可以避免使用复杂的子查询来查找
max()
等等,以及当有多行具有相同的最大值时返回多行的问题(其他答案也会这样做)注意:这是一个仅限mysql的解决方案。我所知道的所有其他数据库都会抛出sql语法错误,并显示消息“groupby子句中未列出非聚合列”或类似消息。因为此解决方案使用未记录的行为,所以更谨慎的人可能希望包含一个测试,以Assert如果mysql的未来版本更改此行为,它仍然有效。
版本5.7更新:
从5.7版开始
sql-mode
设置包括ONLY_FULL_GROUP_BY
默认情况下,要使此功能正常工作,必须没有此选项(编辑服务器的选项文件以删除此设置)。ax6ht2ek3#
采用排名法。
这个sql可以用下面的方式来表示,
select*from users,(select@rn:=0)r order by groupa、age desc、person
@上一个grp为空
@rn:=case when@prev\u grp<>groupa then 1 else@rn+1 end
这是一个三运算符表达式
这样,如果prev\u grp!=其他组rn=rn+1
让rn=1过滤掉您需要的行
tgabmvqs4#
我不会使用组作为列名,因为它是保留字。但是,遵循sql就可以了。
mgdq6dx15#
axiac的解决方案最终对我最有效。然而,我有一个额外的复杂性:一个计算出的“最大值”,来自两列。
让我们用同一个例子:我想要每组中年龄最大的人。如果有同样年纪的人,就选个子最高的人。
我必须执行两次左连接才能得到这种行为:
希望这有帮助!我想应该有更好的方法。。。
8i9zcol26#
我的解决方案只适用于只需要检索一列的情况,但是对于我的需要,它是性能方面最好的解决方案(它只使用一个查询!):
它使用groupconcat来创建一个有序的concat列表,然后我只将子字符串设置为第一个。
oprakyz77#
在oracle中,下面的查询可以给出所需的结果。
b09cbbtk8#
这就是我在mysql中获得每组n个最大行数的方法
工作原理:
自联接到表
分组方式
co.country = ci.country
每组n个元素由) < 1
所以对于3个元素-<3获取最大值或最小值取决于:
co.id < ci.id
co.id<ci.id-最大值co.id>ci.id-最小值
完整示例如下:
mysql选择每个组的n个最大值
r1zk6ea19#
这种方法的好处是允许您按不同的列进行排序,而不会破坏其他数据。在您试图用一列列出订单的情况下,它非常有用,首先列出最重的订单。
资料来源:http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-康卡特
uwopmtnx10#
使用ctes-通用表表达式:
lf5gs5x211#
如果mytable需要id(和所有coulmns)
jc3wubiy12#
让表名为people
fiei3ece13#
正确的解决方案是:
工作原理:
它匹配中的每一行
o
所有的行从b
在列中具有相同的值Group
列中的值更大Age
. 任何一行o
列中没有其组的最大值Age
将匹配中的一行或多行b
.这个
LEFT JOIN
使其与组中最年长的人(包括组中单独的人)匹配一行NULL
来自b
(“组中没有最大年龄”)。使用
INNER JOIN
使这些行不匹配并忽略它们。这个
WHERE
子句只保留具有NULL
在从b
. 他们是每组中年龄最大的人。进一步阅读
在《sql反模式:避免数据库编程的陷阱》一书中解释了此解决方案和其他许多解决方案
gcxthw6b14#
不确定mysql是否有行数函数。如果是这样,你可以用它来得到想要的结果。在sql server上,可以执行类似的操作:
mwecs4sa15#