SQL 服务器:select 只有第一个多列记录实例
SQL Server : select only first instance of record with multiple columns
我正在尝试从记分系统中获取一些个人统计数据。从本质上讲,球队被安排参加比赛
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 将此结果加入回玩家 table,这样我就可以得到个人排名列表
也许您可以虚拟化数据的规范化视图并关闭它而不是 MatchSet table。
;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
)
我认为第一步是编写几个 CTE,将数据放入一个结构中,您可以在其中评估玩家点数,而不管 win/loss。这是一个可能的开始:
;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。
我正在尝试从记分系统中获取一些个人统计数据。从本质上讲,球队被安排参加比赛
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 将此结果加入回玩家 table,这样我就可以得到个人排名列表
也许您可以虚拟化数据的规范化视图并关闭它而不是 MatchSet table。
;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
)
我认为第一步是编写几个 CTE,将数据放入一个结构中,您可以在其中评估玩家点数,而不管 win/loss。这是一个可能的开始:
;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。