3

ほとんどがブリッジ テーブルである PostgreSQL テーブルがありますが、追加のものもあります。

基本的に、ゲーム内のプレイヤーに関する情報を保持します。したがって、ゲーム内のプレーヤーのこのインスタンスには一意の ID があります。次に、ゲーム テーブルの FK である ID と、プレーヤー テーブルの FK である ID。他にも無関係なものがあります。このようなもの:

Table players_games
| id        | 12564
| player_id | 556
| game_id   | 156184

私がやりたいのは、プレーヤーが別のプレーヤーと遊んでいる回数を見つけることです。したがって、プレイヤー 1 がプレイヤー 2 と同じゲームに参加している場合、2 人は一度一緒にプレイしたことになります。ゲームには 2 人以上のプレイヤーがいます。

したがって、私がやりたいことは、player_lo、player_hi、times_played の 3 つの値を保持する新しいテーブルを作成することです。

そして、ペアごとに 1 つの行と、それらがプレイした回数を保持するか、より効率的である場合は、反復ごとに行を 1 に設定して、これらを後で合計したり、分散したりできるように値を設定します。したがって、次のようなものが表示される場合があります。

p1, p2, 1
p1, p2, 1

そして、これらは後で次のように削減されます。

p1, p2, 2

そのため、少し複雑な python スクリプトを書き始める前に、SQL でこれを行う賢い方法があるかどうか、またはプログラミングの労力を軽減できる SQL があるかどうか疑問に思っていました。

4

3 に答える 3

3
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、カウントを取得するためのものです。

于 2012-05-20T13:00:02.537 に答える
3

これを行うには、player_games テーブルで自己結合を行う必要があります。最初のサブクエリは最初のプレーヤー用で、2 番目のサブクエリは 2 番目のプレーヤー用です。「最初の」プレーヤーは、プレーヤー 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 としてもカウントされません)。

また、特定のゲームで 1 人のプレイヤーが複数回出現する可能性がある場合に備えて、内側のサブクエリに「distinct」を追加しました。おそらくこれは必要ありません。確かに、複合キー game_id、player_id に一意のインデックスが必要です。

于 2012-05-20T13:26:35.720 に答える
0
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)
于 2012-05-20T14:27:07.487 に答える