MySQL 5.7.25通过子查询分组并按“非聚合列”错误排序

问题描述 投票:1回答:3

简而言之,我正在尝试按日期对数据集进行排序,然后按另一列进行分组,从而选择每个列的最新行。

查询:

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

示例表:

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-mode的情况下防止发生此错误。

在阅读了有关group byonly_full_group_by的更多信息后,我目前不明白为什么子查询会影响外部查询。

查询是根据https://stackoverflow.com/a/16307932/3852461编写的

mysql group-by mysql-5.7
3个回答
2
投票

如果没有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

1
投票

如果我们想为datetime的每个不同值返回最新的name,那么规范模式将是:

 SELECT t.name
      , MAX(t.datetime) AS latest_datetime 
   FROM requests t
  GROUP
     BY t.name
  ORDER
     BY ...

如果(name,datetime)元组保证是唯一的,我们可以通过将上面的查询结果连接到表来检索具有最新时间的行

 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)元组不是唯一的,那么上面的查询可能会返回具有相同namedatetime值的多行。有处理方法;给定request表的定义,最简单的方法是将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 ... 

0
投票

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;
© www.soinside.com 2019 - 2024. All rights reserved.