Среднее вычисляет средневзвешенное значение на SQL сервере - PullRequest
1 голос
/ 17 июня 2020

Может ли кто-нибудь объяснить мне, почему функция AVG () дает мне средневзвешенное значение в моем коде?

SELECT s.stud_id, s.country, SUM(e.paid) AS totalpaid
    INTO #totalpaid 
    FROM oc.students AS s
    JOIN oc.enrollment AS e ON s.stud_id = e.stud_id
GROUP BY s.country ,s.stud_id;

SELECT DISTINCT s.country, ROUND(AVG(t.totalpaid) OVER (PARTITION BY s.country),0) AS avg_country
    FROM #totalpaid t
    JOIN oc.students s ON t.stud_id = s.stud_id
    JOIN oc.enrollment e ON e.stud_id = s.stud_id; 

Например, в случае Мальты Студент12 посетил 1 курс и заплатил 45 евро, Студент 837 посетил 7 курсов и заплатил в общей сложности 294 евро. Я хотел бы иметь простой расчет (45 + 294) / 2 для среднего, однако система рассчитывает как (1 * 45 + 7 * 294) / 8. Что я делаю не так? enter image description here

Ответы [ 4 ]

2 голосов
/ 17 июня 2020

Во втором запросе, когда вы снова присоединяетесь к своей временной таблице к enrollment, создается одна строка для каждого класса; откуда берутся множественные значения в столбце totalpaid.

Во втором запросе не используются столбцы, которых еще нет во временной таблице, поэтому эти объединения вам вообще не нужны. Это должно дать то, что вы ищете.

SELECT 
  t.country, 
  ROUND(AVG(t.totalpaid) OVER (PARTITION BY t.country),0) AS avg_country
FROM #totalpaid t
GROUP BY 
  t.country;
2 голосов
/ 17 июня 2020

Потому что вы дважды объединяете свои таблицы.

Объединяя операторы INSERT и SELECT, ваш запрос эквивалентен:

SELECT
  DISTINCT s.country, 
  ROUND(AVG(t.totalpaid) OVER (PARTITION BY s.country),0) AS avg_country
FROM (
  SELECT s.stud_id, s.country, SUM(e.paid) AS totalpaid
  FROM oc.students AS s
  JOIN oc.enrollment AS e ON s.stud_id = e.stud_id
  GROUP BY s.country ,s.stud_id    
) t
JOIN oc.students s ON t.stud_id = s.stud_id
JOIN oc.enrollment e ON e.stud_id = s.stud_id

Здесь вы можете ясно видеть таблица students и enrollment соединяются дважды. Это приведет к искажению средней функции.

1 голос
/ 17 июня 2020

А пока нашел решение:

 SELECT
      country,
      ROUND(AVG(totalpaid) OVER (PARTITION BY country),0) AS avg_country
    FROM #totalpaid;

Супер просто :)

1 голос
/ 17 июня 2020
SELECT s.country, sum(e.paid) / count(DISTINCT s.stud_id) as average
FROM oc.students s 
JOIN oc.enrollment e ON e.stud_id = s.stud_id
GROUP BY s.country; 
...