SQL三表连接查询时保留左连接产生的NULL值方法
问题原因
第二版SQL丢失无关联用户的race_number记录,来自两处写法错误:
- 对
user表使用了INNER JOIN:左连接event_entry后未匹配到有效报名记录的行,user_id字段值为NULL,内连接要求必须成功匹配user表记录才会保留行,直接过滤掉了这部分无用户关联的数据 - 过滤条件位置错误:第一版可正常运行的SQL中,
event_entry.event_id=430写在左连接event_entry的ON关联子句中,第二版将该条件挪到了全局WHERE子句。WHERE子句会在左连接执行完成后对全量结果做筛选,所有event_entry字段为NULL的未匹配行,都会因为不满足event_entry.event_id=430的判断被筛除。
修正后SQL
将user表的连接改为左连接,同时把event_entry的event_id过滤条件放回左连接的ON子句中,即可保留无关联用户的记录,对应用户姓名字段返回NULL:
select user.firstname, user.lastname, max(event_timestamps.timestamp) AS last_lap_finish_time, event_timestamps.race_number, count(event_timestamps.race_number) AS lap_count from event_timestamps left join event_entry on event_timestamps.race_number = event_entry.race_number and event_entry.event_id = 430 left join user on user.user_id = event_entry.user_id where event_timestamps.timestamp > '2022-05-28 11:50:00' and event_timestamps.timestamp < '2022-05-29' group by event_timestamps.race_number, user.firstname, user.lastname order by lap_count desc, last_lap_finish_time asc;
补充说明
- 左连接的ON子句条件仅在匹配关联表数据时生效,不会过滤主表
event_timestamps的原有记录,能保证所有符合时间范围的race_number都被保留 - 给统计计算的字段添加了别名,简化排序逻辑的同时方便读取结果
- 分组字段补充了
firstname、lastname,兼容开启ONLY_FULL_GROUP_BY模式的数据库环境,避免SQL执行报错 - 排序逻辑完全匹配需求:优先按完成圈数倒序排列,圈数相同的记录按最后一圈完成时间正序排名。
内容的提问来源于stack exchange,提问作者Meurant Botha
相关产品推荐
相关产品推荐

