MySQL 5.7.25 group by sub-query and order by "nonaggregated column"错误
MySQL 5.7.25 group by sub-query and order by "nonaggregated column" error
简而言之,我正在尝试按日期排序日期集,然后按另一列分组,从而选择每列的最新行。
查询:
SELECT name, datetime
FROM (
SELECT *
FROM `requests`
ORDER BY datetime
) a
GROUP BY a.name;
错误:
#1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'a.datetime' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
示例table:
CREATE TABLE `requests` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`datetime` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
目标是防止此错误发生而无需更改默认 sql-模式。
阅读了更多关于 group by
和 only_full_group_by
的内容后,我目前不明白为什么子查询会影响外部查询。
查询是按照
写的
如果没有像 sum() 或 min() 这样的聚合函数,您不应该使用 GROUP BY。
如果您想要不同的结果,请使用 DISTINCT
SELECT distinct name, datetime
FROM (
SELECT *
FROM `requests`
ORDER BY datetime
) a
但是如果您需要单行作为名称,您应该为日期时间使用聚合函数,例如
SELECT name, max(datetime)
FROM (
SELECT *
FROM `requests`
ORDER BY datetime
) a
group by name
https://www.db-fiddle.com/f/b2EAh6UiVyEdNVbEKbUEcQ/0
SELECT r.name, r.datetime
FROM `requests` r
LEFT JOIN `requests` r2
ON r.name = r2.name
AND r.datetime < r2.datetime
WHERE r2.name IS NULL;
或者只是普通的 GROUP BY
:
SELECT r.name, MAX(r.datetime)
FROM `requests` r
GROUP BY r.name;
如果我们想要 return 最新的 datetime
对于 name
的每个不同值,规范模式将是:
SELECT t.name
, MAX(t.datetime) AS latest_datetime
FROM requests t
GROUP
BY t.name
ORDER
BY ...
如果保证 (name,datetime)
元组是唯一的,我们可以通过将上面的查询结果连接回 table
来检索具有最新时间的行
SELECT r.id
, r.name
, r.datetime
FROM ( SELECT t.name
, MAX(t.datetime) AS latest_datetime
FROM requests t
GROUP
BY t.name
) s
JOIN requests r
ON r.name <=> s.name
AND r.datetime <=> s.latest_datetime
ORDER
BY ...
如果 (name,datetime)
元组不是唯一的,则上面的查询可能 return 多行具有相同值 name
和 datetime
。有一些方法可以解决这个问题;鉴于请求 table 的定义,最简单的方法是将 id
列包装在聚合中,并在外部查询上添加 GROUP BY 子句 ...
SELECT MIN(r.id) AS id
, r.name
, r.datetime
FROM ( SELECT t.name
, MAX(t.datetime) AS latest_datetime
FROM requests t
GROUP
BY t.name
) s
JOIN requests r
ON r.name <=> s.name
AND r.datetime <=> s.latest_datetime
GROUP
BY r.name
, r.datetime
ORDER
BY ...
简而言之,我正在尝试按日期排序日期集,然后按另一列分组,从而选择每列的最新行。
查询:
SELECT name, datetime
FROM (
SELECT *
FROM `requests`
ORDER BY datetime
) a
GROUP BY a.name;
错误:
#1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'a.datetime' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
示例table:
CREATE TABLE `requests` (
`id` int(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`datetime` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
目标是防止此错误发生而无需更改默认 sql-模式。
阅读了更多关于 group by
和 only_full_group_by
的内容后,我目前不明白为什么子查询会影响外部查询。
查询是按照
写的如果没有像 sum() 或 min() 这样的聚合函数,您不应该使用 GROUP BY。
如果您想要不同的结果,请使用 DISTINCT
SELECT distinct name, datetime
FROM (
SELECT *
FROM `requests`
ORDER BY datetime
) a
但是如果您需要单行作为名称,您应该为日期时间使用聚合函数,例如
SELECT name, max(datetime)
FROM (
SELECT *
FROM `requests`
ORDER BY datetime
) a
group by name
https://www.db-fiddle.com/f/b2EAh6UiVyEdNVbEKbUEcQ/0
SELECT r.name, r.datetime
FROM `requests` r
LEFT JOIN `requests` r2
ON r.name = r2.name
AND r.datetime < r2.datetime
WHERE r2.name IS NULL;
或者只是普通的 GROUP BY
:
SELECT r.name, MAX(r.datetime)
FROM `requests` r
GROUP BY r.name;
如果我们想要 return 最新的 datetime
对于 name
的每个不同值,规范模式将是:
SELECT t.name
, MAX(t.datetime) AS latest_datetime
FROM requests t
GROUP
BY t.name
ORDER
BY ...
如果保证 (name,datetime)
元组是唯一的,我们可以通过将上面的查询结果连接回 table
SELECT r.id
, r.name
, r.datetime
FROM ( SELECT t.name
, MAX(t.datetime) AS latest_datetime
FROM requests t
GROUP
BY t.name
) s
JOIN requests r
ON r.name <=> s.name
AND r.datetime <=> s.latest_datetime
ORDER
BY ...
如果 (name,datetime)
元组不是唯一的,则上面的查询可能 return 多行具有相同值 name
和 datetime
。有一些方法可以解决这个问题;鉴于请求 table 的定义,最简单的方法是将 id
列包装在聚合中,并在外部查询上添加 GROUP BY 子句 ...
SELECT MIN(r.id) AS id
, r.name
, r.datetime
FROM ( SELECT t.name
, MAX(t.datetime) AS latest_datetime
FROM requests t
GROUP
BY t.name
) s
JOIN requests r
ON r.name <=> s.name
AND r.datetime <=> s.latest_datetime
GROUP
BY r.name
, r.datetime
ORDER
BY ...