sql查询根据其连续性获取oracle中行的唯一ID

时间:2017-02-04 14:42:30

标签: sql oracle

我有一个问题需要在oracle中使用sql来解决。

我有一个如下所示的数据集:

value | date
------------- 
1 | 01/01/2017 
2 | 02/01/2017 
3 | 03/01/2017 
3 | 04/01/2017
2 | 05/01/2017 
2 | 06/01/2017 
4 | 07/01/2017 
5 | 08/01/2017

我需要以下面的格式显示结果:

value    | date     |   Group
1   |   01/01/2017  |   1
2   |   02/01/2017  |   2
3   |   03/01/2017  |   3
3   |   04/01/2017  |   3
2   |   05/01/2017  |   4
2   |   06/01/2017  |   4
4   |   07/01/2017  |   5
5   |   08/01/2017  |   6

逻辑是,只要value更改date,就会为其分配一个新的group/id,但如果它与前一个group相同,那么它的相同部分{{1} }}

2 个答案:

答案 0 :(得分:0)

以下是使用lag()和累积总和的一种方法:

select t.*,
       sum(case when value = prev_value then 0 else 1 end) over (order by date) as grp
from (select t.*,
             lag(value) over (order by date) as prev_value
      from t
     ) t;

这里的逻辑是简单地计算值从一个月到下一个月的变化次数。

这假定date实际上存储为日期而不是字符串。如果是字符串,那么排序将不正确。转换为日期或使用指定正确排序的列。

答案 1 :(得分:0)

以下是使用Oracle 12中引入的MATCH_RECOGNIZE子句的解决方案。*

select value, dt, mn as grp
from   inputs
match_recognize (
  order by dt
  measures match_number() as mn
  all rows per match
  pattern  ( a b* )
  define   b as value = prev(value)
)
order by dt   --  if needed
;

这是如何工作的:除了SELECT,FROM和ORDER BY之外,查询只有一个子句MATCH_RECOGNIZE。该子句的作用是:它从inputs获取行,并按dt对它们进行排序。然后它搜索模式:一行,标记为a,没有约束,后面是零行或多行b,其中bvalue的条件定义}与prev [ious]行相同。该子句计算的内容或measuresmatch_number() - 模式的第一个“匹配”,第二个匹配等。我们在外部查询中使用此匹配编号作为组编号(grp) - 这就是我们所需要的一切!

* Notes :这样的解决方案的存在表明了为什么海报说明他们的Oracle版本很重要。 (运行语句select * from v$version以查找。)另外:dategroup是Oracle中的保留字,不应用作列名。甚至没有发布制作样本数据。 (有一些解决方法,但在这种情况下不需要它们。)另外,每当在帖子中使用03/01/2017等日期时,请说明是3月1日还是1月3日,“我们”无法告诉。 (在这种情况下并不重要,但在绝大多数情况下都是如此。)