Оконная функция внутри оси, это возможно? - PullRequest
2 голосов
/ 13 июля 2011

У меня есть эта таблица

enter image description here

И мне нужно создать сводную диаграмму, которая отображает эмоции в виде столбцов со средним уровнем эмоций, сгруппированным по user_id, user_date, emotion.Например, для user_id = 1, user_date = 2011-07-13 и emotion = 'Anger' средний уровень emotion_level должен составлять 4,0.

Я создаю сводную точку:

select USER_ID, user_date,  
AVG(case emotion when 'Anger' then convert(float, emotion_level) else 0 end)  as Anger,
AVG(case emotion when 'Sadness' then convert(float, emotion_level) else 0 end) as Sadness,
AVG(case emotion when 'Interest' then convert(float, emotion_level) else 0 end) as Interest
from emotions group by USER_ID, user_date;

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

Мой результат для первого пользователя + emotion = 'Anger' = 2, но должно быть 4.

enter image description here

Полагаю, я должен использовать оконную функцию (over (разбиение по user_id, user_date, emotion)), но не может запустить синтаксис.

Возможно ли это вообще?

Я использую PostgreSQL 9 в prod, но приведенный выше пример написан на SQL Server.

Ответы [ 3 ]

1 голос
/ 13 июля 2011
WITH    q (id, user_id, user_date, emotion, emotion_level) AS
        (
        VALUES
        (1, 1, '2011-07-13'::DATE, 'Anger', 3),
        (2, 1, '2011-07-13'::DATE, 'Anger', 5),
        (3, 1, '2011-07-13'::DATE, 'Sadness', 2),
        (4, 1, '2011-07-13'::DATE, 'Interest', 2),
        (5, 2, '2011-07-13'::DATE, 'Anger', 1),
        (6, 2, '2011-07-13'::DATE, 'Sadness', 4),
        (7, 2, '2011-07-13'::DATE, 'Sadness', 5),
        (8, 2, '2011-07-13'::DATE, 'Interest', 3),
        (9, 3, '2011-07-13'::DATE, 'Anger', 1),
        (10, 3, '2011-07-13'::DATE, 'Sadness', 3),
        (11, 3, '2011-07-13'::DATE, 'Interest', 4),
        (12, 3, '2011-07-13'::DATE, 'Interest', 5)
        ) 
SELECT  user_id, user_date,
        AVG(CASE emotion WHEN 'Anger' THEN emotion_level END)::numeric(3, 2) AS Anger,
        AVG(CASE emotion WHEN 'Sadness' THEN emotion_level END)::numeric(3, 2) AS Sadness,
        AVG(CASE emotion WHEN 'Interest' THEN emotion_level END)::numeric(3, 2) AS Interest
FROM    q
GROUP BY
        user_id, user_date
ORDER BY
        user_id, user_date

Проблема заключалась в том, что первоначально использованные выражения:

AVG(case emotion when 'Interest' then convert(float, emotion_level) else 0 end)

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

1 голос
/ 23 апреля 2019

Сначала я обновил тип данных «emotion_level» до «float» в таблице, а затем выполнил операцию, используя pivot.Если тип данных не обновляется, необходимые значения имеют тип данных int.

select user_id, user_date, Anger, Sadness, Interest 
from (select user_id,user_date,emotion, emotion_level 
from emotions) as emo
pivot(avg(emotion_level) 
for emotion in (Anger, Sadness, Interest)) as P;

Результат вышеуказанного запроса в ссылке ниже https://i.stack.imgur.com/y6ML3.png

0 голосов
/ 13 июля 2011

Я бы определил CTE, затем join для него - ваша главная проблема, вероятно, в том, что вы не group используете emotion_level. Попробуйте это:

WITH average_emotion (user_id, date, emotion, average_level) as 
                     (SELECT user_id, user_date, emotion, AVG(convert(float, emotion_level))
                      FROM emotions
                      GROUP BY user_id, user_date, emotion)
SELECT a.user_id, a.user_date, COALESCE(b.average_level, 0) as Anger
FROM emotions as a
LEFT JOIN average_emotion as b
ON b.user_id = a.user_id
AND b.date = a.user_date
AND b.emotion = 'Anger'
GROUP BY a.user_id, a.user_date

Затем просто добавляйте дополнительные left join каждый раз, когда вам нужен новый столбец.

Есть несколько способов реструктурировать это, в основном относящиеся к остальной части вашей модели данных и желаемому выводу.

...