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

时间:2019-02-22 20:07:31

标签: mysql group-by mysql-5.7

简而言之,我试图按日期排序日期集,然后按另一列分组,从而选择每个日期集的最新行。

查询:

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

编写查询

3 个答案:

答案 0 :(得分:2)

如果没有诸如sum()或min()之类的聚合函数,则不应使用GROUP BY。

如果需要不同的结果,请使用DISTINCT

cur.execute(drop_query, (table_name.replace("'", ""), ))

但是如果您需要单行命名,则应该为日期时间使用聚合函数,例如

SELECT distinct name, datetime
FROM (
    SELECT *
    FROM `requests`
    ORDER BY datetime
) a

答案 1 :(得分: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的多行。有一些处理方法;给定请求表的定义,最简单的方法是将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 ... 

答案 2 :(得分: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;