2010-06-22 4 views
3

У меня есть таблица под названием Игры с колонками: Player1Id, Player2Id, Player1Points, Player2Points.Сложная сумма с группировкой

Образец данных:

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

И я хочу, чтобы иметь список с суммой баллов для каждого игрока, так:

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

Как для того чтобы достигнуть, что в SQL (SQL Server 2008) ? А что, если мне нужна сумма очков , только если какой-то игрок выиграл матч? Можно ли это сделать без использования переменных, циклов и т. Д.?

ответ

2
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 

Урожайность:

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

Запрос будет еще более сложным, если вы добавите больше игроков. Лучше всего записывать счет для каждого игрока на отдельной строке. Вы можете добавить столбец для обозначения игры.

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

Ваш запрос будет тогда просто:

SELECT PlayerId, SUM(Points) 
FROM MyTable 
GROUP BY PlayerId 
ORDER BY PlayerId 
+0

Это должно быть «UNION ALL» (если Джон набрал 3 в двух матчах, он будет засчитан только один раз) – Quassnoi

+0

@Quassnoi, исправлено, спасибо! –

3

Я бы желание реорганизовать данные, возможно:

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

и т.д.

+0

Плюс, если вы начинаете играть с 3 игроками, вам не нужно добавлять столбцы. + 1 для предположения о нормализации данных. – HLGEM

0

Тестовые таблицы:

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; 

Сумма Очки:

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; 

Сумма Очки от выигранных игр:

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; 

Разница:

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; 
1

Это будет рассчитывать только баллы победы:

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 
1

Для того, чтобы ответить на ваш второй вопрос, вы можете затем изменить ответ Маркуса на это:

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 

В зависимости от того, как вы хотите обрабатывать связи, вам нужно будет изменить> =.