SQL:计算每个国家/地区的红卡和黄卡的数量

时间:2019-05-06 20:32:31

标签: sql postgresql

我有一个名为Players的下表:

name      |    memberof   |    country   |   givento   |   cardtype
Ni             1               Australia     7             red
Ju             1               Australia     9             yellow
Is             1               Australia     11            red
Ji             3               Japan         2             red
Su             3               Japan         22            red
Sa             3               Japan         25            yellow
Ji             3               Japan         2             yellow
Ji             3               Japan         2             yellow
Li             4               Thailand      13            red
Li             4               Thailand      13            yellow
Ro             1               Australia     null          null
So             2               Malaysia      null          null

上表显示了球员和他们在足球比赛中收到的卡片。 名称是指玩家的名称,memberof是团队的ID,国家/地区是玩家所属的国家/地区,给定是玩家的ID,卡类型可以是红色或黄色。

我正在尝试编写一个查询,以确定每个国家/地区收到的红卡和黄卡的总数。如果一个国家/地区的玩家之一收到一张卡片,则该国家/地区将被视为收到卡片。

查询的输出应为:

teams      |   reds    |   yellows
Australia       2           1
Malaysia        0           0
Japan           2           3
Thailand        1           1

我有以下两种观点,分别给出了每个国家/地区收到的黄牌和红牌的总数:

create or replace view yellow as select memberof, country, cardtype, 
count(cardtype) over (partition by country) 
as yellows from Players where cardtype = 'yellow';


 create or replace view red as select memberof, country, cardtype, 
 count(cardtype) over (partition by country) 
 as reds from Players where cardtype = 'red';

通过对上述两个查询的“ memberof”结果集执行内部联接,我可以获得一个国家收到的红卡和黄卡的总数。

select distinct y.country, r.reds, y.yellows from yellow y inner join red r on 
y.memberof = r.memberof;

但是,在输出中不包括获得零红卡和零黄卡的马来西亚。

    country  |    reds    |   yellows
   Australia      2            1
   Japan          2            3
   Thailand       1            1

对于收到两种颜色的零色卡的国家,我该如何计算红色和黄色色卡?任何见解都会受到赞赏。

3 个答案:

答案 0 :(得分:4)

使用filter并计划聚合:

select p.country,
       count(*) filter (where p.carttype = 'red') as reds,
       count(*) filter (where p.carttype = 'yellow') as yellows
from players p
group by p.country;

您的带有两个视图和窗口函数的方法似乎很复杂。

答案 1 :(得分:0)

这是简单的条件聚合:

select 
  country, 
  sum(case when cardtype = 'red' then 1 else 0 end) reds,
  sum(case when cardtype = 'yellow' then 1 else 0 end) yellows 
from players 
group by country  

答案 2 :(得分:0)

我喜欢戈登的回答,尽管另一种选择是总结一个案例陈述。如果您需要兼容性,这可能会有所帮助,尽管我认为这会占用更多资源。

SELECT country,
    SUM(
        CASE WHEN cardtype = 'red' OR cardtype = 'yellow' THEN 1
            ELSE 0 
        END
    ) AS CardCount

FROM players
GROUP BY country