Oracle SQL中如何校验登出状态并获取最新登录登出记录
实现方案
你可以通过子查询匹配最新登录/登出时间的方式实现需求,也可以用Oracle特有的模式匹配语法简化代码,两种实现方式如下:
方式1:通用SQL实现(兼容所有Oracle版本)
先获取最新的登录时间、最新的登出时间,再根据时间比对结果返回对应记录:
WITH -- 取最近一次登录时间 latest_login AS ( SELECT MAX(time) AS login_time FROM abc WHERE status = 'Login' ), -- 取最近一次登出时间 latest_logout AS ( SELECT MAX(time) AS logout_time FROM abc WHERE status = 'Logout' ) SELECT status, time FROM abc WHERE -- 匹配最新登录记录 (status = 'Login' AND time = (SELECT login_time FROM latest_login)) OR -- 仅当最近登出时间晚于最近登录时间时,匹配最新登出记录 (status = 'Logout' AND time = (SELECT logout_time FROM latest_logout) AND (SELECT logout_time FROM latest_logout) > (SELECT login_time FROM latest_login)) ORDER BY time ASC;
运行效果完全符合你的要求:
- 未登出场景:最新登出时间早于最新登录时间,仅返回最新登录记录
- 已登出场景:最新登出时间晚于最新登录时间,返回最新的登录+登出两条记录
方式2:Oracle 12c+ 模式匹配实现
如果你的Oracle版本在12c及以上,可以用MATCH_RECOGNIZE语法做事件序列匹配,代码更简洁:
SELECT status, time FROM abc MATCH_RECOGNIZE ( ORDER BY time DESC -- 按时间倒序排列,优先取最新记录 MEASURES s.status AS status, s.time AS time PATTERN ( ^ (login logout?) ) -- 匹配开头的登录记录,以及后面可选的登出记录 DEFINE login AS status = 'Login', logout AS status = 'Logout' ) ORDER BY time ASC; -- 返回结果按时间正序排列
注:你原来的SQL存在语法错误,
in子句里的'login缺少闭合单引号,修正后应为status in ('login','logout')
内容的提问来源于stack exchange,提问作者user14937341
相关产品推荐
相关产品推荐

