如何通过在 python 中的同一个 psql table 中添加 2 列来获得结果
How to get results by adding 2 columns in same psql table in python
我最近开始学习数据库。现在,我正在 python 中的一个数据库支持的应用程序上测试我的技能。我在数据库中创建了 2 个这样的表
CREATE TABLE players
(
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE matches
(
game SERIAL,
winner SERIAL REFERENCES players(id),
loser SERIAL REFERENCES players(id)
);
我想查询那些获得结果的玩家 ID、名称、获胜、匹配,顺序类似于 (id、名称、获胜、匹配)。
我正在使用这段代码来做到这一点
SELECT id, name, count(matches.winner) as wins,
(count(matches.winner) + count(matches.loser)) as match
FROM players LEFT JOIN matches ON players.id = matches.winner
GROUP BY players.id ORDER BY wins
好像不行,请帮我解决一下。
谢谢。
我试过下面这段代码
DB = connect()
c = DB.cursor()
c.execute("""WITH
results AS (
select P.id,
P.name,
1 win
from players P inner join matches M
on M.winner = P.id
union all
select P.id,
P.name,
0 win
from players P inner join matches M
on M.loser = P.id)
select id,
name,
sum(win) wins,
count(*) matches
from results
group by id, name """)
return c.fetchall()
DB.close()
此代码未从数据库中获取任何数据,而是仅返回 []。我也尝试用
替换我的查询字符串
query = oldstring.replace(" ","_")
c.execute(query)
但也没有用。请帮我解决这个问题。
首先,您可能不想对 FK 列使用 SERIAL
数据类型,因为它是一种自增整数类型,适用于 PK,但不适合 FK,最好坚持使用 INTEGER
.
其次,考虑一些约束来执行我们所说的业务规则。总是有两个玩家吗?比赛没有输赢现实吗?如果以平局结束怎么办?
无论如何,让我们暂时保持简单,并假设任何时候两名玩家面对面,其中一个获胜而另一个失败。所以比赛的总数是赢 + 输。
WITH
results AS (
select P.id,
P.name,
1 win
from players P inner join matches M
on M.winner = P.id
union all
select P.id,
P.name,
0 win
from players P inner join matches M
on M.loser = P.id)
select id,
name,
sum(win) wins,
count(*) matches
from results
group by id, name
那么,这里发生了什么:
WITH
是一个 Common Table Expression。它基本上是一个命名子查询。我在这里使用它是为了提高可读性。我可以将子查询放在 FROM
子句中,但这样看起来好多了。
- 您需要以某种方式加入
players
和 matches
,但 matches
中的每一行都引用了两名玩家。好吧,那我们就加入他们两次。
- 当您在
matches.winner
上加入时,每场比赛都会获得一行,这一行有获胜者。这已经足够算赢了,但绝对没有输的信息。
- 第二个查询为每场比赛增加一行,但这次这一行有失败者。
UNION ALL
将两个查询的结果合并到一个结果集中。
- 但我们需要能够区分具有不同结果的行。最简单的方法是对数字求和,所以我设置
1
表示获胜,0
表示失败。
- 最后 group 行现在使用
GROUP BY
和聚合。
您可以用类似的方式计算损失。
我最近开始学习数据库。现在,我正在 python 中的一个数据库支持的应用程序上测试我的技能。我在数据库中创建了 2 个这样的表
CREATE TABLE players
(
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE matches
(
game SERIAL,
winner SERIAL REFERENCES players(id),
loser SERIAL REFERENCES players(id)
);
我想查询那些获得结果的玩家 ID、名称、获胜、匹配,顺序类似于 (id、名称、获胜、匹配)。
我正在使用这段代码来做到这一点
SELECT id, name, count(matches.winner) as wins,
(count(matches.winner) + count(matches.loser)) as match
FROM players LEFT JOIN matches ON players.id = matches.winner
GROUP BY players.id ORDER BY wins
好像不行,请帮我解决一下。
谢谢。
我试过下面这段代码
DB = connect()
c = DB.cursor()
c.execute("""WITH
results AS (
select P.id,
P.name,
1 win
from players P inner join matches M
on M.winner = P.id
union all
select P.id,
P.name,
0 win
from players P inner join matches M
on M.loser = P.id)
select id,
name,
sum(win) wins,
count(*) matches
from results
group by id, name """)
return c.fetchall()
DB.close()
此代码未从数据库中获取任何数据,而是仅返回 []。我也尝试用
替换我的查询字符串query = oldstring.replace(" ","_")
c.execute(query)
但也没有用。请帮我解决这个问题。
首先,您可能不想对 FK 列使用 SERIAL
数据类型,因为它是一种自增整数类型,适用于 PK,但不适合 FK,最好坚持使用 INTEGER
.
其次,考虑一些约束来执行我们所说的业务规则。总是有两个玩家吗?比赛没有输赢现实吗?如果以平局结束怎么办?
无论如何,让我们暂时保持简单,并假设任何时候两名玩家面对面,其中一个获胜而另一个失败。所以比赛的总数是赢 + 输。
WITH
results AS (
select P.id,
P.name,
1 win
from players P inner join matches M
on M.winner = P.id
union all
select P.id,
P.name,
0 win
from players P inner join matches M
on M.loser = P.id)
select id,
name,
sum(win) wins,
count(*) matches
from results
group by id, name
那么,这里发生了什么:
WITH
是一个 Common Table Expression。它基本上是一个命名子查询。我在这里使用它是为了提高可读性。我可以将子查询放在FROM
子句中,但这样看起来好多了。- 您需要以某种方式加入
players
和matches
,但matches
中的每一行都引用了两名玩家。好吧,那我们就加入他们两次。 - 当您在
matches.winner
上加入时,每场比赛都会获得一行,这一行有获胜者。这已经足够算赢了,但绝对没有输的信息。 - 第二个查询为每场比赛增加一行,但这次这一行有失败者。
UNION ALL
将两个查询的结果合并到一个结果集中。- 但我们需要能够区分具有不同结果的行。最简单的方法是对数字求和,所以我设置
1
表示获胜,0
表示失败。 - 最后 group 行现在使用
GROUP BY
和聚合。
您可以用类似的方式计算损失。