Complex sum with grouping
I have table called Games with columns: Player1Id, Player2Id, Player1Points, Player2Points.
Sample dat开发者_JAVA百科a:
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?
I'd be tempted to reorganise the data, perhaps:
Gameid Player Score
1 John 4
2 John 2
1 Piter 1
etc
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
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
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 >=.
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;
精彩评论