检查连续多次经历相同状态的记录
Check records that have gone through the same status more than once in a row
我有状态历史记录 table,我需要知道哪个 id_user 按顺序经过相同的状态。
Table结构
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,它已连续两次通过状态 B。
我怎样才能在我的 table 中找到所有这样的案例?
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 |
--------+-------------+------------+
您只需要在 select
:
中包含您想要的列
select idt_card, status_name, count(*)
from user_status_hist
group by id_user, status_name
having count(*) > 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 分组并计数,您已经知道该怎么做。 (你可以直接在上面显示的解决方案的外部查询中进行。)
我有状态历史记录 table,我需要知道哪个 id_user 按顺序经过相同的状态。
Table结构
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,它已连续两次通过状态 B。 我怎样才能在我的 table 中找到所有这样的案例?
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 |
--------+-------------+------------+
您只需要在 select
:
select idt_card, status_name, count(*)
from user_status_hist
group by id_user, status_name
having count(*) > 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 分组并计数,您已经知道该怎么做。 (你可以直接在上面显示的解决方案的外部查询中进行。)