检查连续多次经历相同状态的记录

Posted

技术标签:

【中文标题】检查连续多次经历相同状态的记录【英文标题】:Check records that have gone through the same status more than once in a row 【发布时间】:2020-11-12 19:44:16 【问题描述】:

我有一个状态历史表,我需要知道哪个 id_user 依次通过了相同的状态。

表结构

create table user (
    id_user number,
    user_name number,
    status_name char(1),
    created_at timestamp,
    primary key (id_user)
);

create table user_status_hist (
    id_user_status_hist number,
    id_user number,
    status_name char(1),
    updated_at timestamp,
    primary key (id_user),
    constraint fk foreign key (id_user) references user(id_user)
);

假设在下面的示例中,对于用户 123,它已连续 2 次通过状态 B。 我怎样才能在我的表中找到所有这样的案例?

select id_user, status_name, updated_at
from user_status_history
where id_user = 123;

--------+-------------+------------+
id_user | status_name | updated_at |
--------+-------------+------------+
    123 |           A | 2020-11-01 |
--------+-------------+------------+
    123 |           B | 2020-11-02 |
--------+-------------+------------+
    123 |           B | 2020-11-05 |
--------+-------------+------------+

通过此查询,我发现我有一个用户多次通过同一状态的情况,但考虑到 updated_at 列,我看不出是否是连续的。

select count(*), idt_card
from user_status_hist
group by id_user, status_name
having count(*) > 1;

我怎样才能得到下面这样的输出? (“计数”列将是他按顺序经历这些状态的次数)

--------+-------------+------------+
id_user | status_name | count      |
--------+-------------+------------+
    123 |           A |          3 |
--------+-------------+------------+
    456 |           B |          2 |
--------+-------------+------------+
    789 |           B |          6 |
--------+-------------+------------+

【问题讨论】:

您也许可以使用match_recognize 做某事,但我并没有完全理解您在示例中是如何获得计数的。 【参考方案1】:

使用 LAG() 分析函数。由于您必须在比较中使用它,并且只能在 SELECT 子句中计算分析函数(该子句应用了所有过滤器之后),因此您必须在子查询中计算分析函数并引用它在外部查询中。

select id_user, status_name, updated_at
from   ( 
         select id_user, status_name, updated_at, 
                lag(status_name) over (partition by id_user order by updated_at) 
                                                                  as prev_status
          from  user_status_hist
       )
where  status_name = prev_status
;

这将为您提供所有事件的完整详细信息。如果您想按 id_user 和 status_name 和 count 进行分组,您已经知道该怎么做。 (可以直接在上图方案的外层查询中进行。)

【讨论】:

【参考方案2】:

您只需要在select 中包含您想要的列:

select idt_card, status_name, count(*)
from user_status_hist
group by id_user, status_name
having count(*) > 1;

【讨论】:

谢谢,但这不会解决“sequentialy”问题。我只需要返回顺序通过相同状态的用户,就像我放的例子一样。

以上是关于检查连续多次经历相同状态的记录的主要内容,如果未能解决你的问题,请参考以下文章

访问连续表单:记录状态

防止快速连续点击button多次执行相同操作

选择连续出现多次的记录

bootstrap-switch:记一次很坑的问题(连续相同状态的多行数据只有第一个显示按钮,其他行没有开关初始化)

使用 pyspark 进行多次连续连接

MySQL - 检查连续列是不是相同并仅显示那些行