2016-08-17 4 views
0

セットアップ後:1で最も一般的な値を計算する<-> 1..n | 0..N <->つのクエリで1

  • メッセージ1..N < - > 1トピック
  • メッセージ0..N < - > 1ムード

テーブル:

Message 
| id 
| text 
| mood_id 
| topic_id 

Topic 
| id 
| title 

Mood 
| id 
| title 

メッセージは特定のトピックに掲載する必要があります。トピックにメッセージを投稿するとき、ユーザーは、そのメッセージをメッセージ自体に書き込む際の気分を付け加えることができます。

私は、次の処理を行い、クエリを記述しようとしています:

  • は、各トピック
  • のメッセージの量を集計し、各トピックのための最も使用される気分

に最適な出力を探します

| topic.id 
| topic.title 
| most_used_mood_id 
| message_count 

私はこのようなもののリストになります多くの進歩なしに今の時間の良い時間のためにこのクエリで頭を抱かせる。メッセージの量を数えることは問題ありませんが、特定のトピックに対するすべてのメッセージの中で最も使用されている感情を計算することは非常に難しいことが判明しました。

正しい方向へのリードが非常に高く評価されています。

+0

質問を編集し、サンプルデータと欲望の結果を提供してください。 –

+0

@GordonLinoffありがとう、私はいくつかのデータを浄化し、ここでそれを提供しようとします。 – dvcrn

答えて

1

は、所望の取得します

select 
    id, topic_id, mood_id, 
    count(topic_id) over (partition by topic_id) message_count, 
    count(mood_id) over (partition by topic_id, mood_id) mood_count 
from message; 

派生テーブルとしてこれを使用する:

だけ messagesを照会凝集
select distinct on (topic_id) 
    t.id, 
    t.title, 
    mood_id as most_used_mood_id, 
    message_count 
from (
    select 
     id, topic_id, mood_id, 
     count(topic_id) over (partition by topic_id) message_count, 
     count(mood_id) over (partition by topic_id, mood_id) mood_count 
    from message 
    ) s 
join 
    topic t on t.id = topic_id 
order by 
    topic_id, mood_count desc; 
+0

すべてのソリューションを試してみて、さまざまなことを試した後、私はこれが最高の作業であることを発見しました。このような種類の文( 'by by by by by and by')は、どのようなパフォーマンスへの影響がありますか?大きなテーブルで拡大縮小できますか? – dvcrn

+0

一般的に[ウィンドウ関数](https://www.postgresql.org/docs/9.5/static/tutorial-window.html)は高価です。単純な 'count(...)'と 'group by ...'は 'count(...)over(partition ...)'より2-4倍速いはずです。しかし、ウィンドウ関数は、*通常の集約*にサブクエリと複雑な結合が必要な場合に、単純なクエリで複数の集約(異なるパーティション上)を可能にします。 100万行のテーブルに対する簡単なテストでは、このソリューションでは約4秒、別の回答では88秒が必要です。エラーのために3番目のクエリをテストできませんでした。 – klin

1

これはあなたの説明に基づく推測です。それは一緒に、メッセージ、トピック、および気分に参加していないし、次にトピックレベルで集計:

select distinct (t.topic_id) mtmo.* 
from (select t.topic_id, t.title, m.mood_id, count(*) as cnt 
     from message_topics m join 
      topic t 
      on mt.topic_id = t.topic_d join 
      message_moods mo 
      on mo.message_id = t.message_id and 
       mo.message_id = mt.message_id 
     group by t.topic_id, t.title 
    ) mtmo 
order by t.topic_id, cnt desc; 
+0

't.mood_id = mo.mood_id'という条件が正しいとは思わないが、' topic'テーブルに 'mood_id'を格納するのは意味がありません。なぜなら各トピックは複数の気分を持つことができるからです。 – sagi

+0

@サギ。 。 。良いキャッチ。これは 'message_id'でなければなりません。 –

1

だけmood_idをしたいので、とてもこの表から選択する必要が:

SELECT tt.topic_id , tt.title, tt.mood_id, 
     (SELECT COUNT(*) FROM message mm WHERE mm.topic_id = tt.topic_id) as message_count 
FROM (
    SELECT s.topic_id,s.title,s.mood_id, 
      ROW_NUMBER() OVER(PARTITION BY s.topic_id,s.title ORDER BY s.cnt DESC) as rnk 
    FROM (
     SELECT t.topic_id,t.title,m.mood_id,count(*) as cnt 
     FROM topic t 
     INNER JOIN message m 
     ON(m.topic_id = t.id) 
     GROUP BY t.topic_id,t.title,m.mood_id) s) tt 
WHERE tt.rnk = 1 
関連する問題