我正在尝试为无法在24小时内登录的SQL报表筛选用户。
交易表
USER_ID STATUS ENTRY_TIMESTAMP USER_NAME
1 SUCCESS 2019-01-15T09:29:48 Alpha
2 FAIL 2019-01-15T09:30:48 Bravo
3 FAIL 2019-01-15T09:31:48 Charlie
2 SUCCESS 2019-01-15T09:32:48 Bravo
4 FAIL 2019-01-15T09:42:48 Delta
预期结果
USER_ID STATUS ENTRY_TIMESTAMP USER_NAME
3 FAIL 2019-01-15T09:31:48 Charlie
4 FAIL 2019-01-15T09:42:48 Delta
注意:USER_NAME Bravo 首次尝试登录失败 @ 9:30:48 ,但能够登录 @ 9:32:48 ,因此我们不必将他置于失败的用户登录报告中
答案 0 :(得分:0)
我想你想要
select t.*
from transactions t
where t.status = 'FAIL' and
not exists (select 1
from transactions t
where t2.user_id = t.user_id and
t2.status = 'SUCCESS' and
t2.timestamp > t.timestamp and
t2.timestamp < t.timestamp + interval '1' day
);
答案 1 :(得分:0)
这是在Oracle 12.1和更高版本中可以完成的操作。对于每个用户,它将使用status = 'FAIL'
拾取一排或多排,只要它们在过去24小时内,并且在同一用户的 行之后没有{ {1}}。
这里有status = 'SUCCESS'
子句可以模拟您的表-它不是解决方案的一部分(删除它,在主查询中使用实际的表名和列名)。我在2019-01-25 17:41运行此查询;为了使结果有意义,我将示例中的日期(从1月15日更改为1月25日)。
WITH
由于您的时间戳记显示了with
transaction (user_id, status, entry_timestamp, user_name) as (
select 1, 'SUCCESS', '2019-01-25T09:29:48', 'Alpha' from dual union all
select 2, 'FAIL' , '2019-01-25T09:30:48', 'Bravo' from dual union all
select 3, 'FAIL' , '2019-01-25T09:31:48', 'Charlie' from dual union all
select 2, 'SUCCESS', '2019-01-25T09:32:48', 'Bravo' from dual union all
select 4, 'FAIL' , '2019-01-25T09:42:48', 'Delta' from dual
)
select *
from transaction
match_recognize(
partition by user_id
order by entry_timestamp
all rows per match
pattern (a+ $)
define a as entry_timestamp >= to_char(sysdate - 1, 'yyyy-mm-dd"T"hh24:mi:ss')
and status = 'FAIL'
);
USER_ID ENTRY_TIMESTAMP STATUS USER_NAME
------- ------------------- ------ ---------
3 2019-01-25T09:31:48 FAIL Charlie
4 2019-01-25T09:42:48 FAIL Delta
,因此我假设它们被保存为字符串。这是非常糟糕的做法;它们应该以{{1}}数据类型存储。