Oracle SQL中的组内组

时间:2017-11-02 06:07:01

标签: sql oracle

我的数据如下:

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字段中加入,以便A将从2017年9月1日开始并于2017年9月9日结束,而它将于2017年9月2日结束,然后从08月 - 2017年。我已尝试过各种分析函数,首先为每个子组分配一个唯一的编号,以获得如下所示的内容:

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 个答案:

答案 0 :(得分:1)

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

Employee

<强>输出:

enter image description here

在这里演示:

Rextester

(该演示在SQL Server中,但查询应该在任何具有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); 正常实现的数据库上运行。)