PostgreSQL查询数据聚合具有默认值

时间:2017-05-23 18:12:39

标签: sql postgresql

我是SQL新手并尝试从在线教程中学习基础知识。我坚持查询,并希望得到一些建议。

目前,目标是使用查询为锦标赛创建一个球员站立桌。我有两张桌子;球员和比赛。

tournament=> select * from players;
 id |       name       
----+------------------
 19 | Melpomene Murray
 20 | Randy Schwartz
 46 | Ricardo
(3 rows)


tournament=> select * from matches;
 winner_id | loser_id 
-----------+----------
        19 |       20
(1 row)

我需要汇总胜利和匹配才能做到这一点:

 id |       name       | wins | p_matches 
----+------------------+------+-----------
 19 | Melpomene Murray |    1 |         1
 20 | Randy Schwartz   |    0 |         1
 46 | Ricardo          |    0 |         0

现在这是我最好的猜测:

tournament=> select players.id, players.name, subq.wins, subq2.p_matches from players,
(select players.id,count(players.id) as wins from players,matches 
where matches.winner_id = players.id group by players.id) as subq,
(select count(*) as p_matches from matches) as subq2;

 id |       name       | wins | p_matches 
----+------------------+------+-----------
 19 | Melpomene Murray |    1 |         1
 20 | Randy Schwartz   |    1 |         1
 46 | Ricardo          |    1 |         1

很大一部分问题源于我的子查询。当我单独运行它时,由于条件限制,我得到一行。我想列出所有ID,其中没有赢的行保持为零。

tournament=> select players.id,count(players.id) as wins from players,matches 
where matches.winner_id = players.id group by players.id;
 id | wins 
----+------
 19 |    1

我听说coalesce可以做这样的事情,但我还没能把它变成工作。想法?

3 个答案:

答案 0 :(得分:1)

还有这个,我不确定哪个表现更好(可能比多个子查询更好)。

select p.id,
       p.name, 
       count(case when m.winner_id = p.id then 1 end) won, 
       count(m.*) total 
from players p 
left join matches m 
on m.winner_id = p.id 
or p.id = m.loser_id 
group by p.id, p.name; 

这将选择所有玩家记录,并且左边连接匹配表(无论玩家ID是否存在),然后对结果进行分组,在这种情况下,可以使用聚合函数,如count。

第一个计数聚合函数只计算获胜者列中获得玩家ID的行(赢),如果他们在任一列中,第二个将计算它们。

答案 1 :(得分:0)

可能是这个?:

t=# with a as (
select p.*, w.w wins, coalesce(w.w, l.l) p_m
from players p
left outer join matches w on w.w = p.id
left outer join matches l on l.l = p.id
)
select id,name, count(wins), count(p_m)
from a
group by id, name
order by id;
 id |       name        | count | count
----+-------------------+-------+-------
 19 |  Melpomene Murray |     1 |     1
 20 |  Randy Schwartz   |     0 |     1
 46 |  Ricardo          |     0 |     0
(3 rows)

答案 2 :(得分:0)

一种简单的方法是在select子句中使用子查询:

select 
  id, 
  name,
  (select count(*) from matches m where p.id = m.winner_id) as wins,
  (select count(*) from matches m where p.id in (m.winner_id, m.loser_id)) as p_matches
from players p
order by id;