Как взять среднее значение двух столбцов построчно в SQL?

У меня есть таблица match, которая выглядит так (см. прикрепленное изображение). Я хотел получить набор данных со столбцом средних значений для home_goal и away_goal, используя этот код.

SELECT 
    m.country_id, 
    m.season,
    m.home_goal,
    m.away_goal,
    AVG(m.home_goal + m.away_goal)  AS avg_goal
FROM match AS m;

Однако я получил эту ошибку

column "m.country_id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 3:  m.country_id,

Мой вопрос: зачем нужен пункт GROUP BY? Почему SQL не может знать, как усреднить два столбца построчно?

Спасибо.

Отметьте свой вопрос с помощью базы данных, которую вы используете.

Gordon Linoff 13.12.2020 13:49
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
1
1 298
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

попробуй это:

SELECT 
    m.country_id, 
    m.season,
    m.home_goal,
    m.away_goal,
    (m.home_goal + m.away_goal)/2  AS avg_goal
FROM match AS m;

Вас попросили указать group_by, поскольку avg() так же, как и sum(), работает с несколькими значениями одного столбца, где вы классифицируете все столбцы, которые не являются операцией по столбцам в группе, с помощью

Вы хотите усреднить два разных столбца - это операции по строкам, а не по столбцам.

Спасибо, ДПХ. Теперь я понимаю причину. Просто для уточнения: встроенные функции, такие как sum, avg, предназначены для столбцов, иначе нужно использовать group by, если вы хотите применить построчно?

Nemo 13.12.2020 02:12

@Nemo, если вам нужны операции по столбцам (горизонтальным), подумайте о формуле (a + b и т. д.). При работе по столбцам вы используете GROUP BY для определения переменных, которые составляют группы (подгруппы и т. д.), для которых вы хотите вычислить (sum(), avg() и т. д.). Когда вы сообщаете столбцу в операции по столбцу без какой-либо функции (sum(), avg() и т. д.), SQL требуется явная информация для группировки, поскольку набор данных сжимается по вертикали операцией по столбцу (что означает значения без операции не будут сжаты, и теперь SQL теряется, поскольку другие сжимаются)

DPH 13.12.2020 02:20

Благодарю за разъяснение. Я не ожидал, что узнаю так много, когда задавал вопрос.

Nemo 13.12.2020 02:30

как взять среднее значение двух столбцов построчно?

Вы не используете AVG() для этого; это агрегатная функция, которая работает с набором строк. Здесь кажется, что вам просто нужно простое математическое вычисление:

SELECT 
    m.country_id, 
    m.season,
    m.home_goal,
    m.away_goal,
    (m.home_goal + m.away_goal) / 2.0 AS avg_goal
FROM match AS m;

Обратите внимание на десятичный знаменатель (2.0): это позволяет избежать целочисленного деления в базах данных, которые его реализуют.

Спасибо за решение, GMB. Но почему я не мог использовать функцию AVG? Не могли бы вы уточнить это в своем ответе, чтобы я принял это как решение?

Nemo 13.12.2020 01:56

@Nemo: нет, это не то, что делает AVG(). Нет встроенной функции для простых вычислений, которые вы хотите сделать.

GMB 13.12.2020 01:58

Вы имеете в виду, что функции AVG, SUM и т. д. нельзя использовать на уровне строк, а только на уровне агрегатов?

Nemo 13.12.2020 02:03

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

Mark Moretto 13.12.2020 02:12

Спасибо, Марк. Ваш комментарий помог мне лучше понять механизм SQL.

Nemo 13.12.2020 02:19

Avg в контексте упомянутой выше функции вычисляет среднее значение значений столбцов, а не среднее значение двух значений в одной строке. Это агрегатная функция, и поэтому требуется предложение group by.

Чтобы получить среднее значение двух столбцов в одной строке, нужно разделить на 2.

Рассмотрим следующую таблицу:

CREATE TABLE Numbers([x] int, [y] int, [category] nvarchar(10));

INSERT INTO Numbers ([x], [y], [category])
VALUES
    (1, 11, 'odd'),
    (2, 22, 'even'),
    (3, 33, 'odd'),
    (4, 44, 'even');

Вот пример использования двух агрегатных функций — AVG и SUM — с GROUP BY:

SELECT
  Category,
  AVG(x) as avg_x,
  AVG(x+y) as avg_xy,
  SUM(x) as sum_x,
  SUM(x+y) as sum_xy
FROM Numbers
GROUP BY Category
  

Результат состоит из двух строк:

Category    avg_x   avg_xy  sum_x   sum_xy
even    3   36  6   72
odd     2   24  4   48

Обратите внимание, что Category доступен в части SELECT, потому что результаты сгруппированы по нему. Если GROUP BY не указан, результатом будет 1 строка, а Category недоступен (какое значение должно отображаться, если у нас есть суммы и средние значения для нескольких строк с разными категориями?).

Что вы хотите, так это вычислить новый столбец, и для этого вы не используете агрегатные функции:

SELECT
  (x+y)/2 as avg_xy,
  (x+y) as sum_xy
FROM Numbers

Это возвращает все строки:

avg_xy  sum_xy
6   12
12  24
18  36
24  48

Если ваши столбцы являются целыми числами, не забудьте обработать округление, если это необходимо. Например (CAST(x AS DECIMAL)+y)/2 as avg_xy,

Простой арифметический расчет:

(m.home_goal + m.away_goal) / 2.0

не совсем эквивалентен AVG(), потому что значения NULL путают его. Базы данных, поддерживающие боковые соединения, предоставляют довольно простой (и эффективный) способ использования AVG() в строке.

Безопасная версия выглядит так:

(coalesce(m.home_goal, 0) + coalesce(m.away_goal, 0)) /
nullif ( (case when m.home_goal is not null then 1 else 0 end +
         case when m.away_goal is not null then 1 else 0 end
        ), 0
      )

Некоторые базы данных имеют расширения синтаксиса, которые позволяют упростить выражение.

Спасибо за новые концепции (coalesce, nullif), Гордон. Что вы имели в виду под некоторыми базами данных, такими как иерархические, реляционные, графовые, сетевые и т. д.?

Nemo 14.12.2020 00:14

@Немо. . . Нет. Все традиционные реляционные базы данных так или иначе расширяют стандарт или поддерживают «необычные» функции стандарта. Например, Postgers поддерживает filter, а MySQL обрабатывает логические значения как целые числа.

Gordon Linoff 14.12.2020 01:22

Другие вопросы по теме