-
12-12-2019 - |
题
我有一个PostgreSQL表,主要是一个桥接表,但它也有一些额外的东西。
本质上,它保存了游戏中玩家的信息。所以我们有一个唯一的id为这个实例的玩家在一个游戏。然后是fk到游戏表的id,以及fk到玩家表的id。还有一些其他不相关的东西。像这样的事情:
Table players_games
| id | 12564
| player_id | 556
| game_id | 156184
我想要做的是找到一个玩家与另一个玩家一起玩的次数。所以,如果player1和player2在同一场比赛中,他们曾经一起玩过一次。有2+玩家在一场比赛中。
所以我想要做的是填充一个新表,它包含三个值:player_lo,player_hi,times_played。
或者每对都有一行和他们玩的次数,或者如果它最终效率更高,那么每个迭代都有一行,并将值设置为1,以便以后可以将它们加在一起,也许是分布式的。所以你可能会看到类似的东西:
p1, p2, 1
p1, p2, 1
这些会在以后减少到:
p1, p2, 2
所以我想知道是否有一些聪明的方法来用SQL来做到这一点,或者如果有SQL可以减少我的编程工作,然后开始编写一个稍微复杂的python脚本来做到这一点。
解决方案
要执行此操作,您需要在Player_Games表上进行自行连接。第一个子查询是第一个玩家,第二个是第二个玩家的第二个子。“第一”播放器是具有较低玩家ID的玩家。
select pg1.player_id as player1, pg2.player_id as player2, count(*) as num_games
from (select distinct game_id, player_id
from players_games pg
) pg1 join
(select distinct game_id, player_id
from players_games pg
) pg2
on pg1.game_id = pg2.game_id and
pg1.player_id < pg2.player_id
group by pg1.player_id, pg2.player_id
.
请注意,连接条件在播放器ID上使用“<”。这是为了防止计数重复(所以玩家A,B也不被称为B,a)。 此外,我在内部子查询中添加了一个“不同”,以防一个玩家对于给定游戏可能出现多次。也许这不是必要的。要确定,您应该在Composite Key Game_ID上具有唯一索引,Player_ID。
其他提示
select p1, p2, count(*) from (
select
pg1.player_id as p1, pg1.game_id, pg2.player_id as p2
from
players_games pg1, players_games pg2
where
pg1.game_id = pg2.game_id and pg1.player_id != pg2.player_id
) foo
group by p1, p2
请注意,这是一个完整的连接 players_games
所以如果桌子很大,它可能会非常慢。关键部分是 group by
为了得到伯爵。
SET search_path='tmp';
DROP TABLE players_game CASCADE;
CREATE TABLE players_game
( game_id INTEGER NOT NULL
, player_id INTEGER NOT NULL
);
INSERT INTO players_game(game_id,player_id) VALUES
(1,100) ,(1,101) ,(2,100) ,(2,101)
,(3,100) ,(3,101) ,(4,102) ,(4,101)
;
WITH pair AS (
SELECT g1.player_id AS p1
, g2.player_id AS p2
FROM players_game g1
JOIN players_game g2 ON g1.game_id = g2.game_id
WHERE g1.player_id < g2.player_id
)
SELECT pa.p1 , pa.p2, COUNT(*) AS num_games
FROM pair pa
GROUP BY p1, p2
ORDER BY num_games DESC
;
.
结果:
SET
ERROR: table "players_game" does not exist
CREATE TABLE
INSERT 0 8
p1 | p2 | num_games
-----+-----+-----------
100 | 101 | 3
101 | 100 | 3
102 | 101 | 1
101 | 102 | 1
(4 rows)
. 不隶属于 StackOverflow