列属性上的条件组

时间:2016-06-14 16:09:57

标签: sql postgresql

我有一个包含以下列的表:pkgenderattribute,并希望为每个性别选择前10个属性。目前我使用两个查询来实现:

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

以及WHERE gender=0的另一个查询。

我可以将其设为一个查询,并按性别输出前10个属性

male_attribute, count, female_attribute, count

3 个答案:

答案 0 :(得分: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;

使用两个性别值,单独的查询可能更简单。但是,如果你有更多的价值观,那么这种方法就有其优点。

编辑:

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;

答案 1 :(得分:2)

可能效率低于其他答案......但更容易阅读...

Working SQL FIDDLE

使用UNION语句可以组合两个具有相同列数和数据类型的查询。

对于要应用于各自集合的限制和顺序,我相信我们只需将选择包装在()中......由于最后一个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)

答案 2 :(得分:1)

我认为数据透视表解决方案可以更好地适应您的情况。回复将如下:

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

要获得这样的结果,PostgreSQL的SQL将是:

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

由于您未指定男性和女性,我将其保留为gender0gender1

解释我认为看起来很奇怪的行:

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

此行将检查来自sum的{​​{1}}或来自gender0的{​​{1}}哪个值更大,并将按sum排序。这样你就可以获得两者中较大的价值。

如果您需要更多解释,请与我们联系。

看到它在这里工作(工作样本的值不同):http://sqlfiddle.com/#!15/c1432/1