Oracle SQL 中的组内组

Posted

技术标签:

【中文标题】Oracle SQL 中的组内组【英文标题】:Group within group in Oracle SQL 【发布时间】:2017-11-02 06:07:00 【问题描述】:

我有以下形式的数据:

ID GROUP DATE
1  A     01-Sep-2017
1  A     02-Sep-2017
1  C     03-Sep-2017
1  C     04-Sep-2017
1  C     05-Sep-2017
1  B     06-Sep-2017
1  B     07-Sep-2017
1  A     08-Sep-2017
1  A     09-Sep-2017
1  C     10-Sep-2017

想要的输出如下:

ID GROUP START_DATE  END_DATE
1  A     01-Sep-2017 02-Sep-2017
1  C     03-Sep-2017 05-Sep-2017
1  B     06-Sep-2017 07-Sep-2017
1  A     08-Sep-2017 09-Sep-2017
1  C     10-Sep-2017 10-Sep-2017

如果我尝试使用简单的 group by,它将使用 GROUP 字段,这样 A 将从 2017 年 9 月 1 日开始,到 2017 年 9 月 9 日结束,而它在 2017 年 9 月 2 日结束,然后从2017 年 9 月 8 日。我尝试了各种分析功能,首先为每个子组分配一个唯一编号,以获得如下结果:

ID GROUP DATE        RANK
1  A     01-Sep-2017 1
1  A     02-Sep-2017 1
1  C     03-Sep-2017 2
1  C     04-Sep-2017 2
1  C     05-Sep-2017 2
1  B     06-Sep-2017 3
1  B     07-Sep-2017 3
1  A     08-Sep-2017 4
1  A     09-Sep-2017 4
1  C     10-Sep-2017 5

现在只是对新字段进行简单分组的情况,但无法获得所需的 RANK 列。

任何有关此方法或任何其他方法的帮助以实现相同目的。

谢谢。

【问题讨论】:

【参考方案1】:

解决此问题的一种方法是行号差异法。用纯语言解释有点困难,所以我邀请你探索下面的演示,把它拆开等等,直到你看到它是如何工作的。基本上,我们采用按日期排序的整个表的行号与按组分区的行号之间的差异。然后,我们可以通过您的组列和此行数差异进行聚合,以获得您想要定位的每个时间块的伪组。

SELECT
    grp,
    MIN(date) AS START_DATE,
    MAX(date) AS END_DATE
FROM
(
    SELECT
        grp, date,
        ROW_NUMBER() OVER (ORDER BY date) -
            ROW_NUMBER() OVER (PARTITION BY grp ORDER BY date) diff
    FROM yourTable
) t
GROUP BY
    grp, diff
ORDER BY
    MIN(date);

输出:

演示在这里:

Rextester

(演示在 SQL Server 中,但查询应该在任何具有ROW_NUMBER 正常实现的数据库上运行。)

【讨论】:

非常感谢,它运行良好。只需根据我的需要进行一些调整。

以上是关于Oracle SQL 中的组内组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle 的组中获得第三个 [重复]

win10系统,计算机>管理下面没有用户和组,我还在哪里找,我想把Oracle的组加到用户里,但是

如何限制查询中返回的组数,而不是 Oracle 中的行数

如何在 Python 中的组内排名?

如何在R中的组内排名?

域内组策略禁用所有客户机USB存储