0

所以我有两张桌子,球员和比赛,结构如下:

                     Table "public.players"
 Column |  Type   |                      Modifiers                       
--------+---------+------------------------------------------------------
 id     | integer | not null default nextval('players_id_seq'::regclass)
 name   | text    | 
 wins   | integer | default 0
 loses  | integer | default 0
 rating | integer | default 1500

                         Table "public.matches"
    Column     |  Type   |                      Modifiers                       
---------------+---------+------------------------------------------------------
 id            | integer | not null default nextval('matches_id_seq'::regclass)
 player1       | integer | 
 player1rating | integer | 
 player2       | integer | 
 player2rating | integer | 
 winner        | boolean | 

如果 player1 赢得那场比赛,则获胜者为 true,如果 player2 赢得那场比赛,则为 false。

使用球员表进行简单的赢/输比较很容易,但是我正在观察两个球员面对面的比较,他们的记录是什么。

所以我对如何总结给定玩家可能被列为玩家1或玩家2的条件感到困惑:P1获胜:

(player1 = <player1> AND winner = true) OR (player2 = <player1> AND winner = false)

P2胜:

(player1 = <player2> AND winner = true) OR (player2 = <player2> AND winner = false) 

损失将与其他玩家获胜相反。

返回信息的东西,例如:

  id  |   name   | wins | loses | rating | wins_v_opp | loses_v_opp
------+----------+------+-------+--------+------------+------------
 4200 | Sinku    |    5 |    48 |   1191 |          1 |          4
 4201 | Kenshiro |   33 |    29 |   1620 |          4 |          1

我在下面的update2之前想出了什么:

CREATE FUNCTION matchup(text, text) AS $$
DECLARE
    player1_name ALIAS FOR $1;
    player2_name ALIAS FOR $2;
BEGIN
    EXECUTE 'SELECT id FROM player WHERE name LIKE $1'
        INTO player1_id
        USING player1_name;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Player1 % not found', player1_name;
    END IF;
    EXECUTE 'SELECT id FROM player WHERE name LIKE $1'
        INTO player2_id
        USING player2_name;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Player2 % not found', player2_name;
    END IF;
    RETURN QUERY EXECUTE 'WITH cte_winners AS (
            SELECT
                CASE WHEN winner THEN m.player1 ELSE m.player2 END AS player,
                COUNT(*) AS wins_v_opp,
                sum(count(*)) over() - COUNT(*) AS loses_v_opp
            FROM matches AS m
            WHERE player1 IN ($1,$2) AND player2 IN ($1,$2)
            GROUP BY player
        )
        SELECT * FROM players AS p
        LEFT OUTER JOIN cte_winners AS cw ON cw.player = p.id WHERE p.id IN ($1,$2)'
    USING player1_id,player2_id;
END;
$$ LANGUAGE plpgsql;    
4

3 回答 3

1

如果要选择由<player1>or赢得的匹配项<player2>,可以使用以下查询:

with cte_winners as (
    select
        id, case when winner then player1 else player2 end as player
    from public.matches
)
select *
from cte_winners
where player in (<player1>, <player2>)

更新

要获得所需的输出,您可以使用以下内容:

with cte_winners as (
    select
        case when winner then m.player1 else m.player2 end as player,
        count(*) as wins_v_opp,
        sum(count(*)) over() - count(*) as loses_v_opp
    from matches as m
    where player1 in (4200, 4201) and player2 in (4200, 4201)
    group by player
)
select *
from players as p
    left outer join cte_winners as cw on cw.player = p.id
where p.id in (4200, 4201)

sql fiddle demo

更新2

with cte_player as (
    select p.id, p.name, p.wins, p.losses, p.rating
    from players as p
    where p.name in ('Sinku', 'Kenshiro')
), cte_winner as (
    select
        case when winner then m.player1 else m.player2 end as player,
        count(*) as wins_v_opp,
        sum(count(*)) over() - count(*) as loses_v_opp
    from matches as m
    where
        m.player1 in (select p.id from cte_player as p) and
        m.player2 in (select p.id from cte_player as p)
    group by player
)
select
    p.id, p.name, p.wins, p.losses, p.rating,
    m.wins_v_opp, m.loses_v_opp
from cte_player as p
    left outer join cte_winner as m on m.player = p.id

sql fiddle demo

于 2013-10-22T17:41:30.623 回答
1
SELECT id, name, wins, losses, rating
      ,count(CASE WHEN winner THEN m.player1 = p.id ELSE m.player2 = p.id END
             OR NULL) AS wins_v_opp
      ,count(CASE WHEN winner THEN m.player2 = p.id ELSE m.player1 = p.id END
             OR NULL) AS loses_v_opp
FROM  (
   SELECT  *, COALESCE(lag(p.id) OVER(), lead(p.id) OVER()) AS id2
   FROM    players p
   WHERE   p.name in ('Sinku', 'Kenshiro')
   ) p
JOIN matches m ON m.player1 IN (id, id2)
              AND m.player2 IN (id, id2)
GROUP BY 1,2,3,4,5;

-> SQL小提琴

于 2013-10-24T17:28:20.127 回答
0
select id
from public.matches
where player1 in ('<player1's number>','<player2's number>')
and player2 in ('<player1's number>','<player2's number>')

应该返回他们相互交手的所有比赛,并且

select id
from public.matches
where (player1 = '<player1's number>' or player2 = '<player1's number>')
and (player1 = '<player2's number>' or player2 = '<player2's number>')
and winner = <condition that shows player1's wins>

返回假设玩家 1 与假设玩家 2 的比赛。

因此获得评级看起来像

select ((
    select count(distinct id)
    from public.matches
    where (player1 = '<player1's number>' or player2 = '<player1's number>')
    and (player1 = '<player2's number>' or player2 = '<player2's number>')
    and winner = <condition that shows player1's wins>
) / (
    select id
    from public.matches
    where player1 in ('<player1's number>','<player2's number>')
    and player2 in ('<player1's number>','<player2's number>')
) * 100) as percent_of_player1_wins
from dual

请注意,我使用了 PLSQL 语法。

于 2013-10-22T17:50:54.550 回答