Вопрос

У меня есть таблица PostgreSQL, которая в основном является таблицей мостов, но у него также есть дополнительные вещи.

По сути, он содержит информацию о игроках в игре. Таким образом, у нас есть уникальный идентификатор для этого экземпляра игрока в игре. Затем идентификатор, который является FK для игрового стола и идентификатор, который является FK для таблицы игрока. Есть также некоторые другие неактуальные вещи. Что-то вроде этого:

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
.

Обратите внимание, что условие соединения использует «<» на идентификаторах проигрывателя.Это должно предотвратить подсчет дубликатов (так что игроки A, B также не считаются B, A).

Кроме того, я добавил «отчетливый» во внутренних подзапрониках, на всякий случай, если один игрок может появиться более одного раза для данной игры.Возможно, это не нужно.Чтобы быть уверенным, у вас должен быть уникальный индекс на композиционном ключевой гейм_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, чтобы он мог быть очень медленным, если таблица большая.Ключевая часть - это генеракодицетагкод для получения количества.

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)
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top