[英]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
. 逻辑是value
随date
变化时,将为其分配一个新的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! 该子句计算或measures
是match_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
进行查找。)另外: date
和group
是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.