Cyclistic共享单车数据分析:MySQL排序时出现NULL异常问题求助
Cyclistic共享单车数据分析SQL排序异常问题排查
问题背景
正在完成谷歌数据分析认证的Cyclistic共享单车顶点项目,使用2022年月度骑行数据,数据包含started_at(租车时间)和ended_at(还车时间)两个datetime字段,通过MySQL的TIMESTAMPDIFF(MINUTE, started_at, ended_at)计算骑行时长trip_length,且已完成数据清理,删除所有含空值的记录。
异常现象
- 降序排序正常显示:执行以下SQL,DBeaver和VS Code均能正常返回数据:
SELECT started_at, ended_at, TIMESTAMPDIFF(MINUTE, started_at, ended_at) AS trip_length FROM bikes.processed ORDER BY 3 DESC LIMIT 1000;
- 升序排序全字段显示NULL:切换为升序排序后,两个工具均返回所有字段为NULL的结果:
SELECT started_at, ended_at, TIMESTAMPDIFF(MINUTE, started_at, ended_at) AS trip_length FROM bikes.processed ORDER BY 3 ASC LIMIT 10;
- 特殊排序方式可正常返回:使用
ORDER BY ISNULL(trip_length), trip_length ASC的SQL能正常显示数据,但对该现象存疑:
SELECT started_at, ended_at, TIMESTAMPDIFF(MINUTE, started_at, ended_at) AS trip_length FROM bikes.processed ORDER BY ISNULL(trip_length), trip_length ASC LIMIT 10;
原因分析
- 核心问题:存在时间逻辑异常的记录
虽然已删除空值记录,但未处理started_at > ended_at的异常行。当租车时间晚于还车时间时,TIMESTAMPDIFF(MINUTE, started_at, ended_at)会返回负数而非NULL。部分客户端工具在升序排序取前N条时,因对极端负数的显示逻辑bug,错误地将整行内容显示为NULL。 - 降序正常的原因
降序排序时,正时长的记录排在前列,取前1000条都是正常数据,不会触发工具的异常显示逻辑;而升序排序时,负数时长的记录排在最前面,触发了工具的显示bug。 - 特殊排序方式生效的原因
由于trip_length实际不为NULL,ISNULL(trip_length)返回0,正常的正时长记录会被优先排序展示,避开了排在最前面的负数时长行,工具因此能正常显示内容。
结果可信度验证
- 验证异常记录存在性
执行以下SQL确认是否存在时间逻辑异常的行:
SELECT COUNT(*) FROM bikes.processed WHERE started_at > ended_at;
若返回大于0的数值,说明确实存在这类异常记录。
2. 查看异常记录的实际值
直接查询异常行,确认trip_length为负数:
SELECT started_at, ended_at, TIMESTAMPDIFF(MINUTE, started_at, ended_at) AS trip_length FROM bikes.processed WHERE started_at > ended_at LIMIT 10;
此时可看到trip_length为负数,工具应能正常显示这些行的内容。
3. 确保分析结果可信的方法
过滤掉时间逻辑异常的记录后,后续分析结果完全可信:
SELECT started_at, ended_at, TIMESTAMPDIFF(MINUTE, started_at, ended_at) AS trip_length FROM bikes.processed WHERE started_at < ended_at ORDER BY trip_length ASC LIMIT 10;
执行上述SQL后,工具能正常显示升序排序的结果,此时的数据为有效清洗后的分析数据。
总结
该问题并非数据本身存在NULL值,而是时间逻辑异常的记录触发了客户端工具的显示bug。通过过滤started_at >= ended_at的异常记录,即可解决升序排序显示NULL的问题,过滤后的分析结果具备可信度。
内容的提问来源于stack exchange,提问作者Kenny Smith
相关产品推荐
相关产品推荐

