绕过 only_full_group_by 限制
Bypassing the only_full_group_by restriction
我有这个简单的 table:
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 | <--
+----------+------------+---------------------+
我想 select 每 deviceId
一行,最近的 loggedAt
。为了清楚起见,我在上面的 table 中用箭头标记了这些行。
如果我在上面的查询中附加 group by id
,我会得到臭名昭著的:
Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'foo.eventName' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
而且我不想更改 sql_mode
。
我已经非常接近我想要使用的东西了:
select deviceId, any_value(eventName), max(loggedAt) from foo group by deviceId;
但显然 any_value
returns 是随机结果。
我该如何解决这个问题?
ONLY_FULL_GROUP_BY
是 一件好事:它执行基本的 SQL 标准规则,MySQL 长期以来一直对此松懈.即使您禁用它,您也会得到与 any_value()
.
相同的结果
您遇到了每组排名前 1 的问题,您无法在其中 整行 包含每台设备的最新日期。聚合不是正确的工具,您需要的是过滤数据集。
一个选项使用相关子查询:
select f.*
from foo f
where f.loggedat = (
select max(f1.loggedate) from foo where f1.deviceid = f.deviceid
)
在MySQL8.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
我有这个简单的 table:
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 | <--
+----------+------------+---------------------+
我想 select 每 deviceId
一行,最近的 loggedAt
。为了清楚起见,我在上面的 table 中用箭头标记了这些行。
如果我在上面的查询中附加 group by id
,我会得到臭名昭著的:
Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'foo.eventName' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
而且我不想更改 sql_mode
。
我已经非常接近我想要使用的东西了:
select deviceId, any_value(eventName), max(loggedAt) from foo group by deviceId;
但显然 any_value
returns 是随机结果。
我该如何解决这个问题?
ONLY_FULL_GROUP_BY
是 一件好事:它执行基本的 SQL 标准规则,MySQL 长期以来一直对此松懈.即使您禁用它,您也会得到与 any_value()
.
您遇到了每组排名前 1 的问题,您无法在其中 整行 包含每台设备的最新日期。聚合不是正确的工具,您需要的是过滤数据集。
一个选项使用相关子查询:
select f.*
from foo f
where f.loggedat = (
select max(f1.loggedate) from foo where f1.deviceid = f.deviceid
)
在MySQL8.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