求助:使用Window Function计算玩家胜率返回全零的问题
问题描述
我有一个小型数据集:
Player 1 W Player 1 L Player 1 L Player 1 W Player 1 W Player 2 L Player 2 L Player 2 W
我尝试使用窗口函数计算玩家的胜率,期望得到如下结果:
Player 1 60% Player 2 33%
但我编写的SQL语句返回全零,代码如下:
create table #t1 ( player_name varchar(10) , win_loss char(1) ) insert into #t1 values ('Player 1','W') ,('Player 1','L') ,('Player 1','L') ,('Player 1','W') ,('Player 1','W') ,('Player 2','L') ,('Player 2','L') ,('Player 2','W') select sum(case when win_loss = 'W' then 1 else 0 end) over (partition by player_name) / count(player_name) over (partition by player_name) from #t1
问题原因与解决方法
原因分析
返回全零是整数除法导致的:SQL中两个整数相除时会自动舍弃小数部分,只保留整数结果。比如Player 1胜场3、总场次5,3/5在整数除法里结果为0,而非0.6。另外,原查询会为每个玩家的每一行都返回相同的胜率值,无法直接得到期望的“每个玩家一行”的结果。
解决方法
方法1:分组聚合(推荐,更简洁)
用GROUP BY分组计算,同时通过强制转换数据类型避免整数除法:
select player_name, cast(sum(case when win_loss = 'W' then 1 else 0 end) * 100.0 / count(*) as decimal(5,1)) || '%' as win_rate from #t1 group by player_name
方法2:修正窗口函数查询
如果必须使用窗口函数,需将其中一个操作数转为浮点型,同时用DISTINCT去重得到每个玩家唯一的胜率:
select distinct player_name, cast( sum(case when win_loss = 'W' then 1.0 else 0 end) over (partition by player_name) / count(player_name) over (partition by player_name) * 100 as decimal(5,1) ) || '%' as win_rate from #t1
补充说明
- 把
1改成1.0或者乘以100.0,是为了让运算转为浮点型,保留小数部分。 cast(...) as decimal(5,1)用来将结果格式化为一位小数,和期望的60%、33%匹配;如果需要整数百分比,可调整为decimal(3,0)。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

