(执行顺序:FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY)
(一)时间函数:TIMESTAMPDIFF(时间差计算)
-
计算用户实际观看秒数,为播放进度、完播率计算提供基础数值。
-
示例 :
sql-- 计算观看秒数(核心用法) TIMESTAMPDIFF(SECOND, start_time, end_time) -- 计算观看分钟数(取整,只算完整单位) TIMESTAMPDIFF(MINUTE, start_time, end_time)
(二)条件函数:IF(三元判断)
-
语法 :
IF(判断条件, 条件成立返回值, 条件不成立返回值) -
业务关联 :动态计算单条播放进度(观看超时长返回 1,否则返回时长比值),是进度统计的核心逻辑。
-
示例 :
sql-- 播放进度计算(核心用法) IF(TIMESTAMPDIFF(SECOND, s, e) > duration, 1, TIMESTAMPDIFF(SECOND, s, e)/duration) -- 完播率判断(满足完播返回1,否则0) IF(TIMESTAMPDIFF(SECOND, s, e) >= duration, 1, 0)
(三)数值函数:ROUND(四舍五入)
ROUND:数值格式化
-
核心说明:对数值四舍五入,保留指定小数位数,让统计结果更整洁,满足业务展示要求。
-
语法 :
ROUND(待格式化数值, 保留小数位数) -
业务关联:播放进度保留 2 位小数、完播率保留 3 位小数,避免出现无限小数(如 2/3≈0.666666→0.667)。
-
示例 :
ROUND(0.666666, 3) → 0.667 -- 完播率保留3位 ROUND(0.833333*100, 2) → 83.33 -- 播放进度保留2位
(四)字符串函数:CONCAT(字符串拼接)
-
核心说明 :将多个字符串 / 数值拼接为一个字符串;数值会自动转为字符串后拼接。
-
语法 :
CONCAT(字符串1, 字符串2, ...) -
业务关联 :将播放进度的数字(如 83.33)和
%拼接为百分比格式(如 83.33%),符合业务展示习惯。 -
示例 :
CONCAT(83.33, "%") → "83.33%" CONCAT("视频", video_id, "完播率") → "视频2001完播率"
三、表关联:JOIN 内连接(含USING简化写法)
- 核心说明:
JOIN(等价于INNER JOIN)
-
又称内连接 ,通过关联字段(如
video_id)匹配两张表的数据,只保留两张表中都存在匹配记录的行。 -
核心:排除「无播放记录的视频」和「无视频信息的播放记录」,符合常规业务统计逻辑。
- 两种关联写法
-
标准写法 :
ON显式指定关联条件,适用于两张表关联字段名不同的场景; -
简化写法 :
USING适用于两张表关联字段名完全相同 的场景(如两张表都是video_id),等价于ON 表1.字段 = 表2.字段,简化代码。 -
语法 :
-- 标准写法:ON 表1 JOIN 表2 ON 表1.关联字段 = 表2.关联字段 -- 简化写法:USING(字段名相同) 表1 JOIN 表2 USING(关联字段) -
业务关联 :关联
tb_user_video_log(播放日志)和tb_video_info(视频信息),获取「播放时间」和「视频时长 / 标签」,为后续计算提供完整数据。 -
示例 :
-- 你的代码中简化写法(推荐,字段名相同时) tb_user_video_log JOIN tb_video_info USING(video_id) -- 等价于标准写法(通用,所有场景) tb_user_video_log t1 JOIN tb_video_info t2 ON t1.video_id = t2.video_id
四、分组与筛选:GROUP BY + HAVING(核心区分WHERE)
GROUP BY:分组查询
-
核心说明 :按指定字段(如
tag、video_id)将数据分组,后续的聚合函数(AVG/SUM/COUNT)会按每组独立计算,而非全表计算。 -
关键规则 :
SELECT中查询的字段,要么在GROUP BY中,要么被聚合函数包裹(否则会报错,MySQL 非严格模式可能不报错,但结果无意义)。 -
业务关联 :按
tag分组算各标签的平均进度、按video_id分组算各视频的完播率,是「按维度统计」的基础。 -
示例 :
GROUP BY tag → 按视频标签分组,每个标签算一次平均进度 GROUP BY video_id → 按视频ID分组,每个视频算一次完播率
HAVING:过滤聚合结果
-
核心说明 :专门过滤 **
GROUP BY分组后的聚合结果 **;不能单独使用,必须和GROUP BY配合。 -
关键区分 :
WHEREvsHAVING(新手必记,核心考点)特性 WHEREHAVING执行时机 聚合计算前过滤原始行 聚合计算后过滤分组结果 过滤对象 原始行数据 分组后的聚合结果 能否用聚合函数 不能 能(核心) -
业务关联 :筛选出「平均播放进度 > 60%」的标签、「完播率 > 0.5」的视频,都是过滤聚合结果,必须用
HAVING。 -
示例 :
HAVING avg_play_progress > 60 → 过滤平均进度超60%的标签 HAVING completion_rate > 0.5 → 过滤完播率超50%的视频
(五)子查询:派生表(FROM 后接子查询)
- 核心说明
- 派生表:子查询的结果集相当于一张「临时表」,必须给临时表起别名 (如
t_progress),否则 MySQL 会报错。
- 适用场景
-
当需要先做聚合统计,再对统计结果做二次处理时使用(如先算数字格式的进度,再拼接 % 符号;先算完播率,再排序)。
-
语法 :
SELECT 外层查询字段 FROM ( -- 内层子查询:聚合统计,生成临时表 SELECT 分组字段, 聚合计算 AS 别名 FROM 表1 JOIN 表2 USING(关联字段) GROUP BY 分组字段 HAVING 聚合结果过滤条件 ORDER BY 聚合字段 ) AS 临时表别名; -- 必须加别名!
六、排序:ORDER BY 升序 / 降序
-
核心说明 :升序(ASC) ,可手动指定降序(DESC)
-
语法 :
ORDER BY 排序字段 [ASC/DESC] -
示例 :ORDER BY avg_play_progress DESC → 按平均播放进度降序
ORDER BY completion_rate ASC → 按完播率升序(默认可省略ASC)
(六)WHEN 条件判断
- 内层核心:
CASE WHEN ... END多条件判断(比 IF () 更通用)
这是 MySQL 的多分支条件函数 ,替代了之前的双分支IF(),支持「多个条件→多个返回值」,是处理多状态字段的核心写法,语法和业务逻辑如下:
CASE
WHEN 条件1 THEN 结果1 -- 关注:+1
WHEN 条件2 THEN 结果2 -- 取关:-1
ELSE 结果3 -- 无行为:0
END