SQL Server-基于条件的SUM()和Group()记录
在我的游戏应用程序中,我有团队,每个团队可以有任意数量的玩家;如果一名球员参加比赛,我会给他5分。每参加一场比赛,他将得到5分加上他的计数 我的存储过程将SQL Server-基于条件的SUM()和Group()记录,sql,sql-server,datetime,group-by,count,Sql,Sql Server,Datetime,Group By,Count,在我的游戏应用程序中,我有团队,每个团队可以有任意数量的玩家;如果一名球员参加比赛,我会给他5分。每参加一场比赛,他将得到5分加上他的计数 我的存储过程将TeamId作为输入参数 现在我想计算每个队每个月的总参与分数,但是这里每个球员的参与分数应该加到球员参加比赛的最后一个月 比如说,Team1有Player1和Player1总共打了4场比赛,2020年4月1场,2020年6月2场,2020年8月1场,在这里进行的4场比赛中,Team1的Player1获得了20个参与点,而最后一场比赛的Play
TeamId
作为输入参数
现在我想计算每个队每个月的总参与分数,但是这里每个球员的参与分数应该加到球员参加比赛的最后一个月
比如说,Team1
有Player1
和Player1
总共打了4场比赛,2020年4月1场,2020年6月2场,2020年8月1场,在这里进行的4场比赛中,Team1的Player1
获得了20个参与点,而最后一场比赛的Player1是在2020年8月进行的,因此所有这20个点都应添加到2020年8月的Team1中
在每位玩家的玩家表中,我有每位玩家的[TotalMatchesPlayed],[TotalMatchesPlayed]*5将给出每位玩家的[TotalParticipationPoints]
这应该对团队中的所有球员重复
SELECT SUM(ISNULL(P.[TotalMatchesPlayed], 0) * 5) AS [ParticipationPoints], CAST(MONTH(PA.[ActivityDate]) AS VARCHAR(2)) AS [Month], CAST(YEAR(PA.[ActivityDate]) AS VARCHAR(4)) AS [Year] FROM [TeamPlayer] TP
INNER JOIN dbo.[Player] P
ON TP.[PlayerId] = P.[PlayerId]
INNER JOIN dbo.[PlayerActivity] PA
ON PA.[PlayerId] = P.[PlayerId] AND PA.[PlayerActivityTyepId] = 14
WHERE TP.[TeamId] = 45
GROUP BY CAST(MONTH(PA.[ActivityDate]) AS VARCHAR(2)), CAST(YEAR(PA.[ActivityDate]) AS VARCHAR(4))
我对这个查询的问题是,[PlayerActivity]表在球员每次参加比赛时都有一行,现在我只想获取最新的日期,并将我无法实现的所有参与点添加到该月份和年份中
我的示例输出应该如下所示
ParticipationPoints | Month | Year
5 06 2020
10 11 2020
创建表格团队成员(
TeamPlayerID int,
PlayerId int,
TeamId INT
);
插入到TeamPlayer值中(1、101、45)
插入到TeamPlayer值中(2、104、19)
插入TeamPlayer值(3、108、45)
创建桌面播放器(
PlayerID int,
名字VARCHAR(1000),
姓氏VARCHAR(1000),
[TotalMatchesPlayed]整数
);
插入玩家值(101,'Joe','Abbey',2)
插入玩家值(102,'Vince','Abbott',3)
插入玩家值(103,'Duke','Abbruzzi',7)
插入玩家值(104,'Kamlesh','Abu',9)
插入玩家值(105,'Evika','Abram',0)
插入玩家值(106,'王子','微妙',2)
插入玩家值(107,'Dick','Absher',1)
插入玩家值(108,'George','Abrell',1)
插入玩家值(109,'William','Peck',2)
插入玩家值(110,'Aaron','Adams',0)
创建表格播放活动(
PlayerActivityId int,
PlayerId int,
playerActivityTypid INT,
活动日期
);
插入到PlayerActivity值中(10114,'2020-04-21')
插入到PlayerActivity值中(210814,'2020-06-17')
插入到PlayerActivity值中(3、101、14、'2020-11-24')
下面链接中的示例表设计和示例数据与我的查询有关
再次重申,如果一个队中的球员打了多场比赛,比如说6场,我需要在他最后一场比赛的月份加上6*5=30分。我的解决方案使用一个子查询来确定每个球员的最后活动日期
选择
PlayerId,
最大(活动日期)为最后日期
从…起
dbo.PlayerActivity
其中playerActivityTypid=14
按PlayerId分组
主查询还使用GROUP BY来聚合每个团队和年/月的结果。这个技巧是在CASE表达式中完成的。这里,我将实际活动日期与子查询确定的最后一个活动日期进行比较。这些点仅在最后一个活动中获得属性,否则为0
选择
TP.TeamId,
总数(
案例
当PA.ActivityDate=X.LastDate时
然后P.TotalMatchesPlayed*5
其他0
结束
)作为参与点,
右(将(100个月以上(PA.ActivityDate)转换为VARCHAR(3)),2)转换为[月],
将(年(PA.ActivityDate)转换为VARCHAR(4))转换为[年]
从…起
dbo.TeamPlayer TP
内部连接dbo.P
在TP.PlayerId=P.PlayerId上
内部连接dbo.PlayerActivity PA
在PA.PlayerId=P.PlayerId和PA.playerActivityTypid=14上
内连接(
挑选
PlayerId,
最大(活动日期)为最后日期
从…起
dbo.PlayerActivity
其中playerActivityTypid=14
按PlayerId分组
)AS X
在X.PlayerId=P.PlayerId上
其中TP.TeamId=45
分组
TP.TeamId,年(PA.ActivityDate),月(PA.ActivityDate)
请注意,我假设每个玩家每天只有一项活动。如果有更多,则会反复总结要点。如果严格按照升序插入PlayerActivityId
值,可以通过使用MAX(PlayerActivityId)
而不是MAX(ActivityDate)
来解决此问题
要获得两位数的月份,我首先计算月份+100,并将其转换为VARCHAR(3)
。这将产生4月份的'104'
。然后使用RIGHT
函数返回最后两个字符,得到结果。当然,您可以使用适当的格式化函数,但我懒得查找要使用的正确函数和格式。我的解决方案使用一个子查询来确定每个播放器的最后活动日期
选择
PlayerId,
最大(活动日期)为最后日期
从…起
dbo.PlayerActivity
其中playerActivityTypid=14
按PlayerId分组
主查询还使用GROUP BY来聚合每个团队和年/月的结果。这个技巧是在CASE表达式中完成的。这里,我将实际活动日期与子查询确定的最后一个活动日期进行比较。这些点仅在最后一个活动中获得属性,否则为0
选择
TP.TeamId,
总数(
案例
当PA.ActivityDate=X.LastDate时
然后P.TotalMatchesPlayed*5
其他0
结束
)作为参与点,
右(将(100个月以上(PA.ActivityDate)转换为VARCHAR(3)),2)转换为[月],
将(年(PA.ActivityDate)转换为VARCHAR(4))转换为[年]
从…起
dbo.TeamPlayer TP
内连接dbo
select year(activitydate) as yyyy, month(activitydate) as mm,
sum(cnt) * 5 as partitionpoints
from (
select pa.*,
count(*) over(partition by playerid) cnt,
row_number() over(partition by playerid order by activitydate desc) rn
from playeractivity pa
) t
where rn = 1
group by year(activitydate), month(activitydate)
order by yyyy, mm
yyyy | mm | partitionpoints
---: | -: | --------------:
2020 | 6 | 5
2020 | 11 | 10