2016-06-14 15 views
0

私はこれらの列を持つテーブルを持っています:pkgenderattribute、性別ごとに上位10の属性を選択したいとします。現在、私はそれを達成するために2つのクエリを使用します。列属性の条件グループ

SELECT attribute, count(attribute) 
FROM tab 
WHERE gender=1 
GROUP BY attribute 
ORDER BY count(attribute) DESC 
LIMIT 10 

WHERE gender=0ための別のクエリ。

は、私は1つのクエリにこれを行い、出力の両方性別ごとのトップ10の属性

male_attribute, count, female_attribute, count

+0

このpostgresqlはありますか? –

+0

@JorgeCampos:はいpg 9。5 – vedar

+1

ユニオン句を使用する – xQbert

答えて

1

私はピボットテーブルのソリューションは、より良いあなたのシナリオに合うだろうと思います。あなたは、私がgender0gender1

としてそれを残した男性と女性であるかを指定しませんでしたので

select attribute, 
     sum(gender0) gender0, 
     sum(gender1) gender1 
    from (select attribute, 
       case when gender=0 then 1 else 0 end as gender0, 
       case when gender=1 then 1 else 0 end as gender1 
      from tab) as tab 
group by attribute 
order by (case when sum(gender0)>sum(gender1) 
       then sum(gender0) 
       else sum(gender1) end) desc 
limit 10 

:PostgreSQLのSQLは次のようになり、このような結果を得るには

attribute  male  female 
    A   10  12 
    B   9   8 
    C   7   8 
    D   6   5 
    E   3   4 

:応答は次のようになります

私はそれが奇妙に見えると思うラインを説明する:

order by (case when sum(gender0)>sum(gender1) 
       then sum(gender0) 
       else sum(gender1) end) desc 

この行は、sumgender0またはsumからgender1までのいずれの値が大きいかチェックし、descによって注文します。そうすれば、あなたは2人のより大きな価値を最初に得るでしょう。

これ以上の説明が必要な場合はお知らせください。

は(値がワーキングサンプルに異なっている)、それはここで働いてください:http://sqlfiddle.com/#!15/c1432/1多分少ない他の回答よりも効率的な...しかし、読みやすい

+1

ありがとう、私は実際に 'クロス集計'を使ってピボットしようとしましたが(初めて)、それは動作しませんでした – vedar

2

あなたがことができます。最も簡単な方法は、変数を使用することです。

SELECT gender, attribute, cnt 
FROM (SELECT ag.*, 
      (@rn := if(@g = gender, @rn + 1, 
         if(@g := gender, 1, 1) 
         ) 
      ) as seqnum 
     FROM (SELECT gender, attribute, count(attribute) as cnt 
      FROM tab 
      GROUP BY gender, attribute 
      ORDER BY gender, cnt DESC 
      ) ag CROSS JOIN 
      (SELECT @rn := 0, @g := -1) params 
    ) ag 
WHERE seqnum <= 10; 

性別の2つの値を使用すると、おそらく別のクエリが簡単になります。しかし、より多くの価値があるなら、このアプローチにはメリットがあります。

EDIT:

Postgresの溶液は非常に簡単です:

select gender, attribute, cnt 
from (select gender, attribute, count(*) as cnt, 
      row_number() over (partition by gender order by count(*) desc) as seqnum 
     from tab t 
     group by gender, attribute 
    ) ga 
where seqnum <= 10; 
+0

答えに感謝しますが、これは私にとっては複雑すぎます。私は単純な解決策を期待して、私はSQLの新しいだと仮定... – vedar

+0

こんにちはゴードンは、このソリューションはpostgresqlで動作しますか? –

+1

@JorgeCampos。 。 。編集されたバージョンはそうです(もっと簡単です)。私はそのタグを間違って読んでいるはずです。 –

2

...

Working SQL FIDDLE

使用UNION文の2つの問合せを、同じ数の列およびデータ型で組み合わせることができます。

それぞれのセットに適用するためには、私は単純に()の選択肢をラップすると信じています...これは最後のORder byとlimitが全体に適用されるため必要ですそうでなければ設定します。

(SELECT attribute, count(attribute), 1 as gender 
FROM tab 
WHERE gender=1 
GROUP BY attribute 
ORDER BY count(attribute) DESC 
LIMIT 10) 

UNION ALL 

(SELECT attribute, count(attribute), 0 as gender 
FROM tab 
WHERE gender=0 
GROUP BY attribute 
ORDER BY count(attribute) DESC 
LIMIT 10) 
+0

素敵でシンプルな、ありがとう – vedar

関連する問題