MySQL 5.7.25 сгруппировать по подзапросу и упорядочить по ошибке «неагрегированный столбец» - PullRequest
0 голосов
/ 22 февраля 2019

Короче говоря, я пытаюсь упорядочить набор дат по дате, а затем сгруппировать по другому столбцу, выбирая, таким образом, самую последнюю строку каждого.

Запрос:

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-режима по умолчанию .

Прочитав больше о group by и only_full_group_by, я в настоящее время не понимаю, почему подзапрос влияет на внешний запрос.

Запрос записывается в соответствии с https://stackoverflow.com/a/16307932/3852461

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

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;
0 голосов
/ 22 февраля 2019

Если мы хотим вернуть самое последнее 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) не является уникальным, то запрос выше потенциально может вернуть несколько строк содинаковые значения name и datetime.Есть подходы к решению этой проблемы;учитывая определение таблицы запросов, проще всего было бы обернуть столбец 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 голосов
/ 22 февраля 2019

Вы не должны использовать GROUP BY без функции агрегирования, такой как sum () или min ().

Используйте 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
...