绕过 only_full_group_by 限制[重复]

Posted

技术标签:

【中文标题】绕过 only_full_group_by 限制[重复]【英文标题】:Bypassing the only_full_group_by restriction [duplicate] 【发布时间】:2021-01-05 17:32:36 【问题描述】:

我有这个简单的表格:

mysql> select deviceId, eventName, loggedAt from foo;
+----------+------------+---------------------+
| deviceId | eventName  | loggedAt            |
+----------+------------+---------------------+
|        1 | foo        | 2020-09-18 21:27:21 |
|        1 | bar        | 2020-09-18 21:27:26 |
|        1 | last event | 2020-09-18 21:27:43 |  <--
|        2 | xyz        | 2020-09-18 21:27:37 |
|        2 | last event | 2020-09-18 21:27:55 |  <--
|        3 | last one   | 2020-09-18 21:28:04 |  <--
+----------+------------+---------------------+

我想为每个 deviceId 选择一行,最近的 loggedAt。为了清楚起见,我在上表中用箭头标记了这些行。

如果我在上面的查询中附加 group by id,我会得到臭名昭著的:

SELECT 列表的表达式 #2 不在 GROUP BY 子句中,并且包含在功能上不依赖于 GROUP BY 子句中的列的非聚合列“foo.eventName”;这与 sql_mode=only_full_group_by 不兼容

我不想更改sql_mode

我已经非常接近我想要使用的东西了:

select deviceId, any_value(eventName), max(loggedAt) from foo group by deviceId;

但显然any_value 返回一个随机结果。

我该如何解决这个问题?

【问题讨论】:

你的 MySQL 版本是多少? @Akina: 8,但我认为这适用于 5.7 及更高版本。 SELECT DISTINCT deviceId, FIRST_VALUE(eventName) OVER (PARTITON BY deviceId ORDER BY loggedAt DESC), MAX(loggedAt) OVER (PARTITON BY deviceId) FROM foo;。仅适用于 8 岁以上。 【参考方案1】:

ONLY_FULL_GROUP_BY一件好事:它强制执行基本的 SQL 标准规则,而 MySQL 长期以来对此一直松懈。即使您禁用它,您也会得到与 any_value() 相同的结果。

您有一个 top-1-per group 问题,您不能整行具有每个设备的最近日期。聚合不是正确的工具,您需要过滤数据集。

一个选项使用相关子查询:

select f.*
from foo f
where f.loggedat = (
    select max(f1.loggedate) from foo where f1.deviceid = f.deviceid
)

在 MySQL 8.0 中,还可以使用row_number()

select *
from (
    select f.*, row_number() over(partition by deviceid order by loggedat desc) rn
    from foo f
) f
where rn = 1

【讨论】:

以上是关于绕过 only_full_group_by 限制[重复]的主要内容,如果未能解决你的问题,请参考以下文章

怎样绕过ip限制?

绕过PHP代码执行中的过滤限制详解

如何绕过 glsl 统一数组大小限制? [复制]

暴力破解绕过token限制

绕过条件格式限制?

绕过SQL限制的方法