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 中的组内组的主要内容,如果未能解决你的问题,请参考以下文章