Leetcode_512_游戏玩法分析2_SQL

本文探讨了如何通过SQL查询分析运动员的活动数据,包括按玩家ID获取最早活动日期、设备ID关联、历史事件比较以及实时排名。核心内容涉及数据筛选、排名算法和设备跟踪技术在体育数据分析中的应用。
with t as (
select player_id, min(event_date) as d
from activity
group by player_id
)

select a.player_id, a.device_id
from activity as a, t
where a.event_date = t.d and a.player_id = t.player_id
select a1.player_id, a1.device_id
from activity as a1
where a1.event_date <= ALL(
    select a2.event_date
    from activity as a2
    where a1.player_id = a2.player_id
)
select player_id, device_id from (
	select
		player_id,
		device_id,
		dense_rank() over(partition by player_id order by event_date) as 排名
	from activity
) as temp where temp.排名 = 1;
<think>嗯,用户让我用MS SQL Server写LeetCode 550题游戏玩法分析IV。我得先看看题目要求是什么。可能用户是正在准备面试或者刷题,需要解决这个问题。首先,我需要回忆或者查找题目描述。 LeetCode 550的题目通常涉及游戏玩法分析,IV的话可能涉及到连续登录或者某种统计。假设题目是计算在第一天登录后第二天也登录的玩家的比例,或者是类似的比例问题。比如,计算在首次登录后的第二天再次登录的玩家占总玩家的比例,四舍五入到小数点后两位。 接下来,我需要考虑如何用SQL实现这个逻辑。可能的步骤包括: 1. 确定每个玩家的首次登录日期。 2. 检查每个玩家是否存在在首次登录日期后一天再次登录的记录。 3. 统计满足条件的玩家数量,并计算占总玩家数的比例。 首先,每个玩家的首次登录日期可以通过GROUP BY和MIN(event_date)来获取。例如: SELECT player_id, MIN(event_date) AS first_login FROM Activity GROUP BY player_id; 然后,需要将原表Activity与这个首次登录表进行连接,条件是同一玩家,且第二次登录的日期正好是首次登录的第二天。比如: SELECT a.player_id FROM Activity a JOIN first_login f ON a.player_id = f.player_id WHERE a.event_date = DATEADD(day, 1, f.first_login); 这里要注意,可能需要用DISTINCT来避免重复计数,因为一个玩家可能在第二天多次登录,但只算一次。 然后,计算满足条件的玩家数除以总玩家数。总玩家数可以通过COUNT(DISTINCT player_id)从Activity表获取。或者,使用子查询先得到每个玩家的首次登录,再统计总数。 最后,将结果四舍五入到两位小数,并用ROUND函数处理。 可能的完整查询结构: WITH first_login AS ( SELECT player_id, MIN(event_date) AS first_login FROM Activity GROUP BY player_id ), consecutive_login AS ( SELECT DISTINCT a.player_id FROM Activity a JOIN first_login f ON a.player_id = f.player_id WHERE a.event_date = DATEADD(day, 1, f.first_login) ) SELECT ROUND( (SELECT COUNT(*) FROM consecutive_login) * 1.0 / (SELECT COUNT(DISTINCT player_id) FROM Activity), 2 ) AS fraction; 这里需要注意除数是否为0的情况,但题目中可能保证至少有一个玩家,所以不需要处理。另外,使用CTE(公共表表达式)可以提高可读性。测试的时候需要考虑边界情况,比如没有玩家满足条件,或者所有玩家都满足的情况。 用户可能遇到的问题包括:如何计算比例,如何处理日期加减,以及如何避免重复计数。此外,确保使用正确的聚合函数和子查询结构。比如,在计算总玩家数时,可能需要用子查询而不是直接从CTE中取,因为可能有玩家在Activity表中存在但未在first_login中出现,但实际GROUP BY已经覆盖所有玩家,所以不会有问题。 另外,检查日期比较是否正确。例如,DATEADD(day,1,first_login)是否正确生成第二天。有些情况下可能需要使用不同的日期函数,但在SQL Server中DATEADD是正确的。 最后,确保输出为小数点后两位,并且类型转换为浮点数,比如乘以1.0来避免整数除法的问题。例如,COUNT(*) * 1.0 将结果转换为浮点数,再进行除法运算。</think>以下是解决LeetCode 550题“游戏玩法分析IV”的MS SQL Server实现思路及代码: ### 题目理解 **要求**:计算在首次登录后第二天再次登录的玩家占总玩家数的比例,结果保留两位小数。 --- ### 解决步骤 1. **获取首次登录日期** 使用 `MIN(event_date)` 找到每个玩家的首次登录日期。 2. **检查次日登录** 通过连接原始表与首次登录表,筛选出满足 `event_date = 首次登录日期 + 1天` 的记录。 3. **计算比例** 统计符合条件的玩家数,除以总玩家数,并处理四舍五入。 --- ### 完整SQL代码 ```sql WITH -- 步骤1:获取每个玩家的首次登录日期 first_login AS ( SELECT player_id, MIN(event_date) AS first_day FROM Activity GROUP BY player_id ), -- 步骤2:找到在首次登录次日有活动的玩家 consecutive_players AS ( SELECT DISTINCT a.player_id FROM Activity a JOIN first_login f ON a.player_id = f.player_id WHERE a.event_date = DATEADD(day, 1, f.first_day) ) -- 步骤3:计算比例(四舍五入到两位小数) SELECT ROUND( (SELECT COUNT(*) FROM consecutive_players) * 1.0 / (SELECT COUNT(DISTINCT player_id) FROM Activity), 2 ) AS fraction; ``` --- ### 关键点解析 1. **CTE分层处理** 使用公共表表达式(CTE)将问题拆解为两个清晰的子任务,提升可读性。 2. **避免重复计数** `SELECT DISTINCT` 确保同一玩家多次次日登录时只计数一次。 3. **浮点数转换** `COUNT(*) * 1.0` 将整数转换为浮点数,避免除法结果被截断为0。 4. **日期处理** `DATEADD(day, 1, first_day)` 准确计算次日日期。 --- ### 示例数据验证 假设输入表 `Activity` 数据: | player_id | event_date | |-----------|------------| | 1 | 2023-01-01 | | 1 | 2023-01-02 | | 2 | 2023-01-02 | | 3 | 2023-01-03 | | 3 | 2023-01-04 | - **首次登录日期**: `(1→2023-01-01), (22023-01-02), (3→2023-01-03)` - **次日登录玩家**: 仅玩家1在2023-01-02登录(符合条件)。 - **计算结果**: `1/3 ≈ 0.33` --- 通过此方法可高效解决问题,逻辑清晰且符合SQL最佳实践。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值