带默认值的PostgreSQL查询数据聚合
我是SQL新手,尝试从在线教程中学习基础知识。我被一个问题难住了,希望你能给我一些建议 目前,目标是使用查询为锦标赛创建一个玩家站立表。我有两张桌子;球员和比赛带默认值的PostgreSQL查询数据聚合,sql,postgresql,Sql,Postgresql,我是SQL新手,尝试从在线教程中学习基础知识。我被一个问题难住了,希望你能给我一些建议 目前,目标是使用查询为锦标赛创建一个玩家站立表。我有两张桌子;球员和比赛 tournament=> select * from players; id | name ----+------------------ 19 | Melpomene Murray 20 | Randy Schwartz 46 | Ricardo (3 rows) tournament=&g
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可以做这样的事情,但我还没能把它变为魔法。想法?可能是这样的:
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)
一种简单的方法是在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;
还有一个问题,我不确定哪一个性能更好(可能比多个子查询更好) 这将选择所有播放器记录,并左键联接matches表(无论播放器id是否存在),然后对结果进行分组,在这种情况下,可以使用诸如count之类的聚合函数
第一个count aggregate函数将只计算winners列(赢)中具有玩家id的行,第二个函数将对任何一列中的行进行计数。麻烦您逐一解释一下,好吗?我对整个shebang很陌生,我想了解您的查询是如何工作的。例如,我从未见过一个以命令“with”而不是“select”开头的查询。我可以按照这个查询的逻辑进行操作,但我认为我无法从查询的该部分访问播放器。相反,postgres认为我做不到:错误:模式“p”不存在,对不起,我错过了关键字中的
,所以PostgreSQL可能把p.id(m.winner\u id,m.loser\u id)
作为一个函数,所以p
将是模式。这似乎很有效,我也很好地理解了它的要点。非常感谢。
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;