SQL查询车辆停放时长:如何找出当前停放超1小时的车辆?
最优SQL解决方案:查询停放时长超1小时的车辆
原SQL的核心问题
- 统计逻辑错误:
COUNT(lane='IN')无法正确统计IN记录数量——SQL中lane='IN'返回布尔值(或1/0),COUNT会把所有非NULL值计入,无论车辆是否有IN记录,该值都会大于0,无法筛选出真实有IN/OUT动作的车辆。正确统计方式应为SUM(CASE WHEN lane = 'IN' THEN 1 ELSE 0 END) > 0。 - 逻辑方向偏差:你的HAVING条件筛选的是既有IN又有OUT的车辆,但预期结果
5678-PC是当前仍在停放(仅存在IN记录)的车辆,原逻辑完全不符合需求。 - 缺少时长计算:未加入时间差判断逻辑,无法筛选停放时长超1小时的车辆。
针对需求的最优方案
根据预期结果,需求应为查询当前仍在停放(无对应OUT记录)且停放时长超过1小时的车辆,以下是两种高效实现方式:
方式1:子查询筛选未离开车辆
SELECT lic_plate, TIMESTAMPDIFF(HOUR, MAX(datetime), '2022-10-07 15:14:17') AS parked_hours FROM parking_table -- 替换为你的实际表名 WHERE lane = 'IN' AND lic_plate NOT IN ( SELECT lic_plate FROM parking_table WHERE lane = 'OUT' ) GROUP BY lic_plate HAVING parked_hours > 1;
方式2:窗口函数获取最新停车动作(更高效)
窗口函数可快速定位每辆车的最新停车状态,适合数据量较大的场景:
WITH latest_parking_actions AS ( SELECT lic_plate, datetime, lane, -- 按车辆分组,按时间倒序排序,最新动作排第1位 ROW_NUMBER() OVER (PARTITION BY lic_plate ORDER BY datetime DESC) AS action_rank FROM parking_table ) SELECT lic_plate, TIMESTAMPDIFF(HOUR, datetime, '2022-10-07 15:14:17') AS parked_hours FROM latest_parking_actions WHERE action_rank = 1 -- 只取最新动作 AND lane = 'IN' -- 最新动作是入场,说明仍在停放 AND TIMESTAMPDIFF(HOUR, datetime, '2022-10-07 15:14:17') > 1;
注:你给出的当前时间
2022-10-07 15:14:17与5678-PC的入场时间完全一致,此时停放时长为0,不符合“超1小时”的条件,推测是笔误。将当前时间改为2022-10-07 16:15:17即可得到预期结果。
扩展:查询历史停放时长超1小时的车辆
如果需要统计所有已离场车辆中停放时长超1小时的,可使用以下SQL:
WITH parking_session AS ( SELECT lic_plate, MAX(CASE WHEN lane = 'IN' THEN datetime END) AS in_time, MAX(CASE WHEN lane = 'OUT' THEN datetime END) AS out_time FROM parking_table GROUP BY lic_plate HAVING out_time IS NOT NULL -- 只统计已离场的车辆 ) SELECT lic_plate, TIMESTAMPDIFF(HOUR, in_time, out_time) AS parked_hours FROM parking_session WHERE TIMESTAMPDIFF(HOUR, in_time, out_time) > 1;
内容的提问来源于stack exchange,提问作者José de Matos
相关产品推荐
相关产品推荐

