2013-10-22 179 views
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贏得了那場比賽,或者如果player2假的贏家是真實的贏得了比賽。

使用球員表進行簡單的贏/輸比較很簡單,但我正在觀察比較兩名球員相互面對對手的情況,以及他們對對方的記錄。

所以我對我怎麼會總結困惑,其中給出一個給定的球員可能被列爲要麼PLAYER1或player2條件: 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;  

回答

1
如果你想選擇由 <player1><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>) 

update

,從而獲得所需的輸出你可以使用這樣的事情:

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

UPDATE2

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

+0

我就更新了原來的職位:) – OverlordQ

+0

@OverlordQ您的評論還沒有完成:) –

+0

現在$ 10,000的問題是,如果我不知道前面的玩家ID我想按名稱選擇,我不需要加入CTE的球員嗎? – OverlordQ

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> 

返回一個假想的PLAYER1贏得了對一個假設player2比賽。

因此得到一個得分看起來像

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語法。

+0

我已經計算好了收視率,我想看看是否有一個查詢可以返回我存儲的數據(勝,輸,等級)以及兩個額外的欄目,詳細列出兩名球員之間的比賽。 – OverlordQ

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; 

- >SQLfiddle

+0

這不需要是左手,所以即使他們還沒有匹配,我仍然會返回他們的W/L /等級記錄嗎?改變了模式,並以[this]結尾(http://sqlfiddle.com/#!12/f92bb/1/0) – OverlordQ

+0

@OverlordQ:沒錯。如果你願意的話,可以把'LEFT'加到'JOIN'上。 –