views:

57

answers:

6

Hi

I have table called Games with columns: Player1Id, Player2Id, Player1Points, Player2Points.

Sample data:

Player1Id    Player2Id    Player1Points    Player2Points
---------    ---------    -------------    -------------
John         Piter        4                 1
John         Adam         2                10
Piter        Adam         4                 2

And I want to have a list with sum of points for each player, like that:

PlayerId    Points
--------    ------
John         6
Piter        5
Adam        12

How to achive that in SQL (SQL Server 2008)? And what if I need a sum of points only if some player won a match? Can it be done without using variables, loops etc?

+1  A: 
SELECT Player1Id AS PlayerId, SUM(Player1Points) AS Points FROM
(SELECT Player1Id, Player1Points FROM MyTable
UNION ALL
SELECT Player2Id, Player2Points FROM MyTable) t1
GROUP BY Player1Id
ORDER BY Player1Id

Yields:

PlayerId       Points
--------       ------
Adam               12
John                6
Piter               5

The query will get even more complicated if you add more players. It would be best to record the score for each player on a distinct row. You could add a column to designate the game.

PlayerId   Points   GameId
--------   ------   ------
John            4        1
Piter           1        1
John            2        2
Adam           10        2
Piter           4        3
Adam            2        3

Your query would then be simple:

SELECT PlayerId, SUM(Points)
FROM MyTable
GROUP BY PlayerId
ORDER BY PlayerId
Marcus Adams
This should be `UNION ALL` (if John scored 3 in two matches it would be counted only once)
Quassnoi
@Quassnoi, fixed, thanks!
Marcus Adams
+3  A: 

I'd be tempted to reorganise the data, perhaps:

Gameid Player Score
  1    John     4
  2    John     2
  1    Piter    1

etc

Patrick
Plus if you start to have games with 3 players, you don't have to add columns. + 1 for suggesting normalizing the data.
HLGEM
A: 

Test tables:

DECLARE @Table TABLE (Player1Id VARCHAR(17), Player2Id VARCHAR(17), Player1Points INT, Player2Points INT);
INSERT INTO @Table
    SELECT 'John', 'Piter', 4, 1 UNION ALL
    SELECT 'John', 'Adam', 2, 10 UNION ALL
    SELECT 'Piter', 'Adam', 4, 2;

Sum Points:

WITH CTE (PlayerId, Points) AS (
    SELECT Player1Id, Player1Points FROM @Table
     UNION ALL
    SELECT Player2Id, Player2Points FROM @Table
)
SELECT PlayerId, SUM(Points) FROM CTE GROUP BY PlayerId;

Sum Points from won games:

WITH CTE (PlayerId, Points, Won) AS (
    SELECT Player1Id, Player1Points, CASE WHEN Player1Points > Player2Points THEN 1 ELSE 0 END FROM @Table
     UNION ALL
    SELECT Player2Id, Player2Points, CASE WHEN Player2Points > Player1Points THEN 1 ELSE 0 END FROM @Table
)
SELECT PlayerId, SUM(Points) FROM CTE WHERE Won = 1 GROUP BY PlayerId;

Difference:

WITH CTE (PlayerId, Points) AS (
    SELECT Player1Id, CASE WHEN Player1Points > Player2Points THEN Player1Points - Player2Points ELSE (Player2Points - Player1Points) * -1 END FROM @Table
     UNION ALL
    SELECT Player2Id, CASE WHEN Player2Points > Player1Points THEN Player2Points - Player1Points ELSE (Player1Points - Player2Points) * -1 END FROM @Table
)
SELECT PlayerId, SUM(Points) FROM CTE GROUP BY PlayerId;
Don
+1  A: 

This will count only victory scores:

SELECT  player, SUM(score) AS score
FROM    (
        SELECT  player1id AS player, player1points AS score
        FROM    mytable
        WHERE   player1points > player2points
        UNION ALL
        SELECT  player2id, player2points
        FROM    mytable
        WHERE   player2points > player1points
        ) q
GROUP BY
        player
Quassnoi
+1  A: 

To answer your second question, you could then alter Marcus' answer to this:

SELECT
    Player1Id,
    SUM(Player1Points)
FROM
(
    SELECT Player1Id, Player1Points FROM MyTable WHERE Player1Points >= Player2Points
    UNION ALL
    SELECT Player2Id, Player2Points FROM MyTable WHERE Player2Points >= Player1Points
) t1
GROUP BY
    Player1Id

Depending on how you want to handle ties, you would need to change the >=.

Tom H.
A: 

Thanks for smart&quick response! Stack is awesome :) Sorry - I can't vote you up case I don't have any reputation points yet.