简体   繁体   English

sql查询基于连续性获取oracle中一行的唯一id

[英]sql query to get unique id for a row in oracle based on its continuity

I have a problem that needs to be solved using sql in oracle. 我有一个需要在oracle中使用sql解决的问题。

I have a dataset like given below: 我有一个如下所示的数据集:

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

I need to show the result in the below format: 我需要以以下格式显示结果:

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

The logic is whenever value changes over date , it gets assigned a new group/id , but if its the same as the previous one , then its part of the same group . 逻辑是valuedate变化时,将为其分配一个新的group/id ,但是如果它与前一个相同,则属于同一group

Here is one method using lag() and cumulative sum: 这是使用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;

The logic here is to simply count the number of times that the value changes from one month to the next. 这里的逻辑是简单地计算该值从一个月到下个月的变化次数。

This assumes that date is actually stored as a date and not a string. 假定date实际上存储为日期而不是字符串。 If it is a string, then the ordering will not be correct. 如果是字符串,则排序将不正确。 Either convert to a date or use a column that specifies the correct ordering. 要么转换为日期,要么使用指定正确顺序的列。

Here is a solution using the MATCH_RECOGNIZE clause, introduced in Oracle 12.* 这是使用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
;

Here is how this works: Other than SELECT, FROM and ORDER BY, the query has only one clause, MATCH_RECOGNIZE. 这是这样工作的:除SELECT,FROM和ORDER BY之外,查询只有一个子句MATCH_RECOGNIZE。 What this clause does is: it takes the rows from inputs and it orders them by dt . 该子句的作用是:从inputs获取行,并按dt对其进行dt Then it searches for patterns: one row, marked as a , with no constraints, followed by zero or more rows b , where b is defined by the condition that the value is the same as for the prev[ious] row. 然后,它搜索模式:标记为a一行,没有任何约束,紧接着是零个或多个行b ,其中b由条件确定,即value与上一行相同。 What the clause calculates or measures is the match_number() - first "match" of the pattern, second match etc. We use this match number as the group number ( grp ) in the outer query - that's all we needed! 该子句计算或measuresmatch_number() -模式的第一个“匹配”,第二个匹配等。我们将这个匹配号用作外部查询中的组号( grp )-这就是我们所需要的!

*Notes : The existence of solutions like this shows why it is important for posters to state their Oracle version. *注意 :这样的解决方案的存在说明了为什么张贴者声明其Oracle版本很重要。 (Run the statement select * from v$version to find out.) Also: date and group are reserved words in Oracle and shouldn't be used as column names. (运行语句select * from v$version进行查找。)另外: dategroup是Oracle中的保留字,不应用作列名。 Not even for posting made-up sample data. 甚至不用于发布虚构的样本数据。 (There are workarounds but they aren't needed in this case.) Also, whenever using dates like 03/01/2017 in a post, please indicate whether that is March 1 or January 3, there's no way for "us" to tell. (有解决方法,但在这种情况下是不需要的。)此外,每当在帖子中使用日期如03/01/2017时,请指出是3月1日还是1月3日,“我们”无法告诉。 (It wasn't important in this case, but it is in the vast majority of cases.) (在这种情况下这并不重要,但在绝大多数情况下都是如此。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM