2011-07-12 11 views
2

私は、この表ピボット内の窓機能は可能ですか?

enter image description here

を持っていると私はピボットを作成する必要があり、user_idは、user_date、感情によってグループ化された平均emotion_levelで、列として感情を表示します。たとえば、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を計算します。

は私がピボットを作成します。

最初のユーザ+感情のための私の結果は= = 2 '怒り'、それは4

enter image description here

する必要があります、私は推測する、私は(user_date、USER_IDによってパーティション(上のウィンドウ関数を使用する必要があります、感情))、構文を実行することはできません。

それはまったく可能ですか?

私はprodでPostgreSQL 9を使用していますが、上記の例はSQL Serverで書かれています。

答えて

1
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 

問題は、最初に使用する式はということでしたNULLとなるため、平均でInterestには寄与しません。

0

CTEを定義すると、joinとなります。あなたの主な問題はおそらく、あなたが,に入っていないということです。これを試してください:

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を追加してください。

これは、主に残りのデータモデルと望ましい出力に関する、これを再構成する方法がいくつかあります。彼らのように扱われるべきである一方で

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

、特定の日に特定のユーザーのすべてのレコードを超える平均し、0として非Interestエントリを扱う:

関連する問題