У меня есть таблица, которая выглядит как этот вызывающий "makerar"
cname | wmname | avg
--------+-------------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
И я хочу выбрать максимальное среднее значение для каждого имени.
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
но я получу ошибку,
ERROR: column "makerar.wmname" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
так что я делаю это
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname, wmname;
однако это не даст ожидаемых результатов, и ниже показан неправильный вывод.
cname | wmname | max
--------+--------+------------------------
canada | zoro | 2.0000000000000000
spain | luffy | 1.00000000000000000000
spain | usopp | 5.0000000000000000
Фактические результаты должны быть
cname | wmname | max
--------+--------+------------------------
canada | zoro | 2.0000000000000000
spain | usopp | 5.0000000000000000
Как я могу решить эту проблему?
Примечание. Эта таблица представляет собой ПРОСМОТР, созданный в результате предыдущей операции.
sql
group-by
aggregate-functions
postgresql-9.1
Случайный парень
источник
источник
wmname="usopp"
ожидается, а не напримерwmname="luffy"
?Ответы:
Да, это общая проблема агрегации. До SQL3 (1999) выбранные поля должны появляться в
GROUP BY
предложении [*].Чтобы обойти эту проблему, вы должны вычислить агрегат в подзапросе, а затем объединить его с собой, чтобы получить дополнительные столбцы, которые вам нужно показать:
Но вы также можете использовать оконные функции, которые выглядят проще:
Единственное, что есть в этом методе, это то, что он покажет все записи (оконные функции не группируются). Но он покажет правильную (т.е. максимальную на
cname
уровне)MAX
страну в каждом ряду, так что решать вам:Решение, возможно, менее элегантное, чтобы показать единственные
(cname, wmname)
кортежи, соответствующие максимальному значению:[*]: Интересно, что хотя вид спецификации позволяет выбирать не сгруппированные поля, основным движкам это не очень нравится. Oracle и SQLServer просто не позволяют этого вообще. Mysql раньше разрешал это по умолчанию, но теперь, начиная с 5.7, администратору необходимо включить эту опцию (
ONLY_FULL_GROUP_BY
) вручную в конфигурации сервера, чтобы эта функция поддерживалась ...источник
MAX
(см. Ответ @ypercube, в моем ответе есть и другое решение), но не так, как вы это делаете. Проверьте ожидаемый результат.avg
percname
), но не ограничивает строки результата (как этого хочет OP). Смотреть фактические результаты следует в абзаце вопроса.ONLY_FULL_GROUP_BY
в MySQL 5.7 не активирует путь в SQL стандарт определяет , когда столбцы могут быть исключены изgroup by
(или делает MySQL ведут себя как Postgres). Он просто возвращается к старому поведению, где вместо этого MySQL возвращает случайные (= "неопределенные") результаты.В Postgres вы также можете использовать специальный
DISTINCT ON (expression)
синтаксис:источник
BY cname
?Проблема с указанием не сгруппированных и неагрегированных полей в
group by
выборках заключается в том, что движок не может знать, какое поле записи он должен вернуть в этом случае. Это первое? Это последний? Обычно не существует записей, которые естественно соответствуют агрегированному результату (min
иmax
являются исключениями).Тем не менее, есть обходной путь: сделайте также обязательные поля агрегированными. В posgres это должно работать:
Обратите внимание, что это создает массив всех wnames, упорядоченных по avg, и возвращает первый элемент (массивы в postgres основаны на 1).
источник
Используя
rank()
оконную функцию :Заметка
Любой из них сохранит несколько максимальных значений на группу. Если вам нужна только одна запись на группу, даже если существует более одной записи с avg, равным max, вы должны проверить ответ @ ypercube.
источник
Для меня это не "общая проблема агрегации", а просто неправильный запрос SQL. Единственный правильный ответ для «выберите максимальное среднее значение для каждого имени ...»
Результат будет:
Этот результат в целом отвечает на вопрос «Каков наилучший результат для каждой группы?» , Мы видим, что лучший результат для Испании - 5, а для Канады - 2. Это правда и ошибки нет. Если нам нужно также отобразить wmname , мы должны ответить на вопрос: «Какое ПРАВИЛО выбрать wmname из полученного набора?» Давайте немного изменим входные данные, чтобы уточнить ошибку:
Какой результат вы ожидаете на этот запрос запущенных:
SELECT cname, wmname, MAX(avg) FROM makerar GROUP BY cname;
? Это должно бытьspain+luffy
илиspain+usopp
? Зачем? В запросе не определено, как выбрать «лучше» wmname если подходит несколько, поэтому результат также не определяется. Вот почему интерпретатор SQL возвращает ошибку - запрос неверен.Другими словами, нет правильного ответа на вопрос «Кто лучший в
spain
группе?» , Луффи не лучше, чем usopp, потому что у usopp тот же «счет».источник
SELECT cname, id, MAX(avg) FROM makerar GROUP BY cname;
что привело к этой вводящей в заблуждение ошибке.Это похоже на работу
источник
Недавно я столкнулся с этой проблемой, когда пытался сосчитать с помощью
case when
, и обнаружил, что изменение порядка операторовwhich
andcount
решает проблему:Вместо использования - в последнем, где я получил ошибки, яблоки и апельсины должны появляться в агрегатных функциях
источник
which
Заявление?