sql - 行编号和子分组

标签 sql oracle grouping rank

我希望有人能帮忙;我将自己归类为 Oracle/SQL 的新手,但到目前为止,我已经设法获得了所需的内容,但在如何处理查询方面遇到了障碍。

我有一个事件数据集,每个事件都有一个唯一的 ID,该 ID 在其整个生命周期中保持一致;每个事件都有多个按时间指示的事件;每个事件可以有不同的状态。请参阅下面的示例集。

我想要实现的是一个列表,其中包含按事件 ID 和时间排序的数据,以及每个事件的增量 ID (1,2,3,4);但我还需要一个从 1 开始的辅助列,当状态与前一行不同时递增。

下面是我的数据示例:

    ACTIVITY_ID | EVENT_TIMESTAMP      | EVENT_STATUS
    --------------------------------------------------------
    A001        | 01/01/2020 09:00:00  | STATUS A
    A001        | 01/01/2020 10:10:00  | STATUS B
    A001        | 01/01/2020 11:20:00  | STATUS C
    A001        | 01/01/2020 12:30:00  | STATUS C
    A002        | 01/01/2020 13:40:00  | STATUS F
    A002        | 01/01/2020 17:50:00  | STATUS F
    A002        | 01/01/2020 17:53:00  | STATUS G

利用 ROW_NUMBER 和 PARTITION BY 我获得了一个输出,它为我提供了我的有序列表,如下所示:

    ACTIVITY_ID | EVENT_TIMESTAMP      | EVENT_STATUS   | EVENT_NUMBER
    --------------------------------------------------------------------
    A001        | 01/01/2020 09:00:00  | STATUS A       | 1
    A001        | 01/01/2020 10:10:00  | STATUS B       | 2  
    A001        | 01/01/2020 11:20:00  | STATUS C       | 3
    A001        | 01/01/2020 12:30:00  | STATUS C       | 4
    A002        | 01/01/2020 13:40:00  | STATUS F       | 1
    A002        | 01/01/2020 17:50:00  | STATUS F       | 2
    A002        | 01/01/2020 17:53:00  | STATUS G       | 3

我正在努力解决的是我正在寻找的子分组结果(如下),这是否应该与 ROW_NUMBER 相同,但针对事件状态进行分区?我尝试了各种尝试,但当状态更改时分区总是重置为 1,而不是从 1 开始,然后随着每次更改而递增?

    ACTIVITY_ID | EVENT_TIMESTAMP      | EVENT_STATUS   | EVENT_NUMBER | EVENT_STATUS_GROUP
    ----------------------------------------------------------------------------------------
    A001        | 01/01/2020 09:00:00  | STATUS A       | 1            | 1
    A001        | 01/01/2020 10:10:00  | STATUS B       | 2            | 2
    A001        | 01/01/2020 11:20:00  | STATUS C       | 3            | 3
    A001        | 01/01/2020 12:30:00  | STATUS C       | 4            | 3
    A001        | 01/01/2020 12:30:00  | STATUS A       | 5            | 4

    A002        | 01/01/2020 13:40:00  | STATUS F       | 1            | 1
    A002        | 01/01/2020 17:50:00  | STATUS F       | 2            | 1
    A002        | 01/01/2020 17:53:00  | STATUS G       | 3            | 2

我希望这足够清楚,如果还不够清楚,请提出任何问题。

最佳答案

您可以使用DENSE_RANK()分析函数:

SELECT t.*, 
       ROW_NUMBER() OVER (PARTITION BY ACTIVITY_ID ORDER BY EVENT_STATUS ) 
                                                                         AS EVENT_NUMBER,
       DENSE_RANK() OVER (PARTITION BY ACTIVITY_ID ORDER BY EVENT_STATUS ) 
                                                                   AS EVENT_STATUS_GROUP
  FROM tab t
 ORDER BY ACTIVITY_ID, EVENT_NUMBER 

Demo

关于sql - 行编号和子分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63141031/

相关文章:

mySQL SUM 先前的分组查询

Java Hibernate JPQL 查询(聚合函数 : count)

php - 使用 SQL 计算列中的单词

java - 当所有参数都为空时 COALESCE 的替代方案

oracle - 如何通过mview名称获取刷新作业id?

java - 如何在 hibernate 中渲染具有多个表的树结构?

php - 按键拆分和分组数组

rust - 如何在 Rust 的向量中对连续整数进行分组?

sql - 获取从开始到结束日期范围(包括边界)之间的事件行

mysql - 从表中检索数据,其中有 3 个表 A、B、C 。表C的引用在B中,表B的引用在A中