我有一个包含以下列的表:pk
,gender
,attribute
,并希望为每个性别选择前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
答案 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)
可能效率低于其他答案......但更容易阅读...
使用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
由于您未指定男性和女性,我将其保留为gender0
和gender1
解释我认为看起来很奇怪的行:
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