дизайн таблицы для отслеживания личных встреч? - PullRequest
0 голосов
/ 10 января 2012

У меня проблемы с созданием работоспособного дизайна таблицы для отслеживания результатов личных встреч между пользователями.

У всех пользователей есть UID. Отдельные результаты матчей сохраняются в другой таблице, и у каждого матча есть свой UID.

То, что я хочу, это иметь возможность получить что-то вроде этого с помощью простого выбора:

Player   vs.    Opponent   Wins   Losses   Draws
Bob             John       5      2        1
Bob             Sam        0      3        2
John            Bob        2      5        1

Я могу извлечь эти данные из необработанных результатов сопоставления с помощью некоторых манипуляций в PHP, но это довольно дорого, поэтому я бы хотел использовать задания cron и сохранять эти "готовые" статистические данные в таблице для быстрого чтения.

Меня сбивает с толку тот факт, что один набор данных (2 игрока, выигрыш, проигрыш, счет ничьих) можно прочитать в двух направлениях, в зависимости от того, какую точку зрения игрока вы хотите, как показано выше для Боба и Джона.

Я мог бы сделать таблицу следующим образом:

[player]  [opponent]  [wins]  [losses]  [draws]

но тогда каждому «набору» потребуется две строки ...

[player]  [opponent]  [wins]  [losses]  [draws]
bob       john        5       2         1
john      bob         2       5         1

и это дублирование кажется, что оно может вызвать у меня проблемы позже, хотя изо всех сил я не могу придумать причину, почему, просто СУХОЙ и все такое ...

Предложения

Ответы [ 2 ]

1 голос
/ 10 января 2012

Предполагая, что у вас есть таблица (MatchID, Player1ID, Player2ID, Player1Score, Player2Score ...), с одной строкой для каждого матча (то есть без дублирования)

Вы можете получить все совпадения для игрока через:

SELECT * from Matches WHERE Player1ID = @ID OR Player2ID = @ID

Возможно, немного более полезно, однако, немного переставить данные, чтобы они всегда были игроком и противником:

SELECT MatchID, Player1ID, Player2ID, Player1Score, Player2Score ... FROM Matches where Player1ID = @ID
UNION
SELECT MatchID, Player2ID, Player1ID, Player2Score, Player1Score ... FROM Matches where Player2ID = @ID

(обратите внимание, что как идентификатор, так и порядок оценок меняются во втором операторе объединения)

Вы также можете обобщить это для построения статистики:

 SELECT stats.Player, stats.Opponent, SUM(stats.PlayerWin) AS Wins, SUM(stats.Draw) AS Draws, SUM(stats.OpponentWin) AS Losses
 FROM (
    SELECT Player1ID AS Player, Player2ID AS Opponent, 
        CASE WHEN Player1Score > Player2Score THEN 1 ELSE 0 END AS PlayerWin,
        CASE WHEN Player1Score = Player2Score THEN 1 ELSE 0 END AS Draw, 
        CASE WHEN Player2Score > Player1Score THEN 1 ELSE 0 END AS OpponentWin
    UNION
    SELECT Player2ID AS Player, Player1ID AS Opponent, 
        CASE WHEN Player2Score > Player1Score THEN 1 ELSE 0 END AS PlayerWin,
        CASE WHEN Player2Score = Player1Score THEN 1 ELSE 0 END AS Draw, 
        CASE WHEN Player1Score > Player2Score THEN 1 ELSE 0 END AS OpponentWin
     ) stats
 GROUP BY stats.Player, stats.Opponent

Полагаю, моя общая мысль в том, что вы можете сделать это в любом случае, они примерно одинаково сложны (если вы помещаете данные в базу данных дважды, вы должны убедиться, что вы синхронизируете их при обновлении. данные в базу данных один раз, вы должны считать их дважды, когда вы делаете статистику. Кроме того, если вы помещаете данные в базу данных дважды, это немного усложняет ситуацию со стороны базы данных, поскольку MatchID больше не будет уникальным.)

1 голос
/ 10 января 2012

Я видел, что упомянутый вами подход к дублированию эффективно используется. Пока вы знаете о дублировании, справиться с ним не так уж и сложно.

Если вы хотите избежать дублирования, вам, вероятно, понадобится больше кода и больше сложности кода: чтобы показать все результаты для одного игрока, вам нужно будет найти записи, где этот игрок либо «Игрок» или «Противник».

Один (я бы сказал, что) полезный способ сообщить обо всех записях игроков (против их оппонентов) состоит в том, чтобы отображать каждую запись «против» дважды - один раз как игрок, сгруппированный вместе, и один раз как противник, в каждом из наборов рекордов для своих противников:

Player   vs.    Opponent   Wins   Losses   Draws
Bob             John       5      2        1
Bob             Sam        0      3        2
John            Bob        2      5        1
John            Sam        1      2        1
Sam             Bob        3      0        2
Sam             John       2      1        1
...