如何获得包含每个分组集的最大值的行?
我在这个问题上看到过一些过于复杂的变化,没有一个能给出好的答案。我试着把最简单的例子放在一起:
如果有这样一个表,其中有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条答案
按热度按时间uidvcgyl1#
我针对sqlite(可能还有mysql)的简单解决方案:
但是,它在postgresql和其他一些平台中不起作用。
在postgresql中,可以使用distinct on子句:
3phpmpom2#
让表名为people
ldfqzlk83#
在mysql中有一种非常简单的方法:
这是因为在mysql中不允许聚合非groupby列,在这种情况下mysql只返回第一行。解决方案是首先对数据进行排序,这样对于每个组,您需要的行是第一个,然后按您需要的值所在的列进行分组。
您可以避免使用复杂的子查询来查找
max()
等等,以及当有多行具有相同的最大值时返回多行的问题(其他答案也会这样做)注意:这是一个仅限mysql的解决方案。我所知道的所有其他数据库都会抛出sql语法错误,并显示消息“groupby子句中未列出非聚合列”或类似消息。因为此解决方案使用未记录的行为,所以更谨慎的人可能希望包含一个测试,以Assert如果mysql的未来版本更改此行为,它仍然有效。
版本5.7更新:
从5.7版开始
sql-mode
设置包括ONLY_FULL_GROUP_BY
默认情况下,要使此功能正常工作,必须没有此选项(编辑服务器的选项文件以删除此设置)。xe55xuns4#
zlwx9yxi5#
不确定mysql是否有行数函数。如果是这样,你可以用它来得到想要的结果。在sql server上,可以执行类似的操作:
m4pnthwp6#
在oracle中,下面的查询可以给出所需的结果。
dsf9zpds7#
axiac的解决方案最终对我最有效。然而,我有一个额外的复杂性:一个计算出的“最大值”,来自两列。
让我们用同一个例子:我想要每组中年龄最大的人。如果有同样年纪的人,就选个子最高的人。
我必须执行两次左连接才能得到这种行为:
希望这有帮助!我想应该有更好的方法。。。
vzgqcmou8#
我的解决方案只适用于只需要检索一列的情况,但是对于我的需要,它是性能方面最好的解决方案(它只使用一个查询!):
它使用groupconcat来创建一个有序的concat列表,然后我只将子字符串设置为第一个。
xn1cxnb49#
如果mytable需要id(和所有coulmns)
qfe3c7zg10#
使用ctes-通用表表达式:
wlzqhblo11#
这就是我在mysql中获得每组n个最大行数的方法
工作原理:
自联接到表
分组方式
co.country = ci.country
每组n个元素由) < 1
所以对于3个元素-<3获取最大值或最小值取决于:
co.id < ci.id
co.id<ci.id-最大值co.id>ci.id-最小值
完整示例如下:
mysql选择每个组的n个最大值
z9ju0rcb12#
这种方法的好处是允许您按不同的列进行排序,而不会破坏其他数据。在您试图用一列列出订单的情况下,它非常有用,首先列出最重的订单。
资料来源:http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-康卡特
oprakyz713#
我不会使用组作为列名,因为它是保留字。但是,遵循sql就可以了。
mqkwyuun14#
正确的解决方案是:
工作原理:
它匹配中的每一行
o
所有的行从b
在列中具有相同的值Group
列中的值更大Age
. 任何一行o
列中没有其组的最大值Age
将匹配中的一行或多行b
.这个
LEFT JOIN
使其与组中最年长的人(包括组中单独的人)匹配一行NULL
来自b
(“组中没有最大年龄”)。使用
INNER JOIN
使这些行不匹配并忽略它们。这个
WHERE
子句只保留具有NULL
在从b
. 他们是每组中年龄最大的人。进一步阅读
在《sql反模式:避免数据库编程的陷阱》一书中解释了此解决方案和其他许多解决方案
zzwlnbp815#
你也可以试试