SQL Server: выберите только первый экземпляр записи с несколькими столбцами - PullRequest
0 голосов
/ 27 января 2019

Я пытаюсь получить отдельные статистические данные из системы учета результатов.В сущности, команды запланированы на матчи

Match
---------
Matchid (uniqueidentifier)
SessionId (int)
WeekNum (int)

Эти матчи разбиты на сеты, в которых два отдельных игрока из команды играют друг с другом

MatchSet
-----------
SetId (int)
Matchid (uniqueidentifier)
HomePlayer (int)
AwayPlayer (int)
WinningPlayer (int)
LosingPlayer (int)
WinningPoints (int)
LosingPoints (int)
MatchEndTime (datetime)

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

Я пытался использовать CTE для нумерации строк

;WITH cte AS
(
   SELECT *,
       ROW_NUMBER() OVER (PARTITION BY MatchId ORDER BY MatchEndTime) AS rn
   FROM 
       (SELECT 
            SetId, MS.MatchId, WinningPlayer, LosingPlayer, 
            HomePlayer, AwayPlayer, WinningPoints, LosingPoints, MatchEndTime
        FROM 
            MatchSet MS 
        INNER JOIN 
            [Match] M ON M.MatchId = MS.MatchId AND M.[Session] = @SessionId
    )

, но я изо всех сил, так как игрок может быть либо домашним игроком, либо игроком на выезде в данном сете (также может быть победителем или проигравшим)

В идеале,этот результат затем можно объединить на основе WinningPlayer или LosingPlayer обратно в таблицу игроков, что позволило бы мне получить список отдельных позиций

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Я думаю, что первым шагом является написание пары CTE, которые передают данные в структуру, где вы можете оценивать игровые очки независимо от выигрыша / проигрыша. Вот возможное начало:

;with PlayersPoints as 
(
   select m.MatchId
        ,m.SessionId 
        ,m.WeekNum
        ,ms.SetId       
        ,ms.WinningPlayer as PlayerId
        ,ms.WinningPoints as Points
        ,'W' as Outcome
        ,ms.MatchEndTime 
    from MatchSet ms
    join Match m on on ms.MatchId = m.MatchId
        and m.SessionId = @SessionId 

   union all 

   select m.MatchId
        ,m.SessionId 
        ,m.WeekNum
        ,ms.SetId   
        ,ms.LosingPlayer as PlayerId
        ,ms.LosingPoints as Points
        ,'L' as Outcome
        ,ms.MatchEndTime 
    from MatchSet ms
   join Match m on on ms.MatchId = m.MatchId
        and m.SessionId = @SessionId 
)
, PlayerMatch as 
(
   select SetId
        ,WeekNum
        ,MatchId
        ,PlayerId
        ,row_number() over (partition by PlayerId, WeekNum order by MatchEndTime) as PlayerMatchSequence
    from PlayerPoints 
)
....

Первый CTE вытягивает очки для каждого игрока, а второй CTE определяет его соответствие. Таким образом, для расчета отдельных очков, вы должны искать PlayerMatchSequence = 1.

0 голосов
/ 27 января 2019

Возможно, вы могли бы виртуализировать нормализованное представление ваших данных и отключить их вместо таблицы MatchSet.

;WITH TeamPlayerMatch AS
(
    SELECT TeamID,PlayerID=WinnningPlayer,MatchID,Points = MS.WinningPoints, IsWinner=1 FROM MatchSet MS INNER JOIN TeamPlayer T ON T.PlayerID=HomePlayer
    UNION ALL
    SELECT TeamID,PlayerID=LosingPlayer,MatchID,Points = MS.LosingPoints, IsWinner=0 FROM MatchSet MS INNER JOIN TeamPlayer T ON T.PlayerID=AwayPlayer
)

,cte AS
(
   SELECT *,
       ROW_NUMBER() OVER (PARTITION BY MatchId ORDER BY MatchEndTime) AS rn
   FROM 
       (SELECT 
            SetId, MS.MatchId, PlayerID, TeamID, Points, MatchEndTime, IsWinner
        FROM 
            TeamPlayerMatch MS 
        INNER JOIN 
            [Match] M ON M.MatchId = MS.MatchId AND M.[Session] = @SessionId
        WHERE
            IsWinner=1
    )
...