The Oracle CQL MATCH_RECOGNIZE
clause and its sub-clauses perform pattern recognition in Oracle CQL queries.
The MATCH_RECOGNIZE
clause performs pattern recognition in an Oracle CQL query as Example 19-1 shows. This query will export (make available for inclusion in the SELECT
) the MEASURES
clause values for events (tuples) that satisfy the PATTERN
clause regular expression over the DEFINE
clause conditions.
Example 19-1 Pattern Matching With MATCH_RECOGNIZE
<query id="detectPerish"><![CDATA[ select its.badItemId from tkrfid_ItemTempStream MATCH_RECOGNIZE ( PARTITION BY itemId MEASURES A.itemId as badItemId PATTERN (A B* C) DEFINE A AS (A.temp >= 25), B AS ((B.temp >= 25) and (to_timestamp(B.element_time) - to_timestamp(A.element_time) < INTERVAL "0 00:00:05.00" DAY TO SECOND)), C AS (to_timestamp(C.element_time) - to_timestamp(A.element_time) >= INTERVAL "0 00:00:05.00" DAY TO SECOND) ) as its ]]></query>
(pattern_partition_clause::=, pattern_measures_clause::=, pattern_def_dur_clause::=)
(pattern_clause::=, pattern_skip_match_clause::=, pattern_definition_clause::=, duration_clause::=, subset_clause::=)
Using MATCH_RECOGNIZE
, you define conditions on the attributes of incoming events and identify these conditions by using identifiers
called correlation variables. Example 19-1 defines correlation variables A
, B
, and C
. A sequence of consecutive events in the input stream satisfying these conditions constitutes a pattern.
The output of a MATCH_RECOGNIZE
query is always a stream.
The principle MATCH_RECOGNIZE
sub-clauses are:
MEASURES
: exports (makes available for inclusion in the SELECT
) attribute values of events that successfully match the pattern you specify.
PATTERN
: specifies the pattern to be matched as a regular expression over one ore more correlation variables.
DEFINE
: specifies the condition for one or more correlation variables.
To refine pattern recognition, you may use the optional MATCH_RECOGNIZE
sub-clauses, including:
For more information, see:
In Oracle CQL (as in SQL), the FROM
clause is evaluated before the WHERE
clause.
Consider the following Oracle CQL query:
SELECT ... FROM S MATCH_RECOGNIZE ( .... ) as T WHERE ...
In this query, the S MATCH_RECOGNIZE ( .... ) as T
is like a subquery in the FROM
clause and is evaluated first, before the WHERE
clause.
Consequently, you rarely use both a MATCH_RECOGNIZE
clause and a WHERE
clause in the same Oracle CQL query. Instead, you typically use a view to apply the required WHERE
clause to a stream and then select from the view in a query that applies the MATCH_RECOGNIZE
clause.
Example 19-2 shows two views, e1p1
and e2p2
, each applying a WHERE
clause to stream S
to pre-filter the stream for the required events. The query q
then selects from these two views and applies the MATCH_RECOGNIZE
on this filtered stream of events.
Example 19-2 MATCH_RECOGNIZE and the WHERE Clause
<view id="e1p1"> SELECT * FROM S WHERE eventName = 'E1' and path = 'P1' and statName = 'countValue' </view> <view id="e2p2"> SELECT * FROM S WHERE eventName = 'E2' and path = 'P2' and statName = 'countValue' </view> <query id="q"> SELECT T.e1p1Stat as e1p1Stat, T.e2p2Stat as e2p2Stat FROM e1p1, e2p2 MATCH_RECOGNIZE( ALL MATCHES PATTERN(A+) DURATION 60 MINUTES DEFINE A as (A.e1p1Stat < 1000 and A.e2p2Stat > 2000 and count(A) > 3) ) as T </query>
For more information, see opt_where_clause::=
The MATCH_RECOGNIZE
clause identifies the following types of matches:
singleton: a correlation variable is a singleton if it occurs exactly once in a pattern, is not defined by a SUBSET
, is not in the scope of an alternation, and is not quantified by a pattern quantifier.
References to such a correlation variable refer to this single event.
group: a correlation variable is a group if it occurs in more than one pattern, is defined by a SUBSET
, is in the scope of an alternation, or is quantified by a pattern quantifier.
References to such a correlation variable refer to this group of events.
When you reference singleton and group correlation variables in the MEASURES
and DEFINE
clauses, observe the following rules:
For singleton correlation variables, you may reference individual event attributes only, not aggregates.
For group correlation variables:
If you reference an individual event attribute, then the value of the last event to match the correlation variable is returned.
If the correlation variable is not yet matched, NULL
is returned. In the case of count(A.*)
, if the correlation variable A
is not yet matched, 0 is returned.
If the correlation variable is being referenced in a definition of the same variable (such as DEFINE A as A.balance > 1000
), then the value of the current event is returned.
If you reference an aggregate, then the aggregate is performed over all events that have matched the correlation variable so far.
For more information, see:
You can use any built-in, Colt, or user-defined aggregate function in the MEASURES
and DEFINE
clause of a MATCH_RECOGNIZE
query.
When using aggregate functions, consider the following:
Section 19.1.3.2, "Operating on the Same Correlation Variable"
Section 19.1.3.3, "Referencing Variables That Have not Been Matched Yet"
Section 19.1.3.4, "Referencing Attributes not Qualified by Correlation Variable"
For more information, see:
Section 19.1.3.5, "Using count With *, identifier.*, and identifier.attr"
Section 9.1, "Introduction to Oracle CQL Built-In Aggregate Functions"
Section 11.1, "Introduction to Oracle CQL Built-In Aggregate Colt Functions"
In the DEFINE
clause, any aggregate function on a correlation variable X
is a running aggregate: that is, the aggregate includes all preceding matches of X
up to and including the current match. If the correlation variable X
has been completely matched so far, then the aggregate is final, otherwise it is running.
In the MEASURES
clause, because it is evaluated after the match has been found, all aggregates are final because they are computed over the final match.
When using a SUBSET
clause, be aware of the fact that you may inadvertently imply a running aggregate as Example 19-3 shows.
Example 19-3 Implied Running Aggregate
... PATTERN (X+ Y+) SUBSET Z = (X, Y) DEFINE X AS X.price > 100, Y AS sum(Z.price) < 1000 ...
Because correlation variable Z
involves Y
, the definition of Y
involves a running aggregate on Y
.
For more information, see:
In both the MEASURES
and DEFINE
clause, you may only apply an aggregate function to attributes of the same correlation variable.
For example: the use of aggregate function correlation
in Example 19-4 is invalid.
Example 19-4 Invalid Use of Aggregate Function
... MEASURES xycorr AS correlation(X.price, Y.price) PATTERN (X+ Y+) DEFINE X AS X.price <= 10, Y AS Y.price > 10 ...
The correlation
aggregate function may not operate on more than one correlation variable.
In the DEFINE
clause, you may reference a correlation variable that has not been matched yet. However, you should use caution when doing so. Consider Example 19-5.
Example 19-5 Referencing a Variable That has not Been Matched Yet: Invalid
PATTERN (X+ Y+) DEFINE X AS count(Y.*) >= 3 Y AS Y.price > 10,
Although this syntax is legal, note that in this particular example, the pattern will never match because at the time X
is matched, Y
has not yet been matched, and count(Y.*)
is 0.
To implement the desired behavior ("Match when the price of Y
has been greater than 10, 3 or more times in a row"), implement this pattern as Example 19-6 shows.
Example 19-6 Referencing a Variable That has not Been Matched Yet: Valid
PATTERN (Y+ X+) DEFINE Y AS Y.price > 10, X AS count(Y.*) >= 3
For more information, see Section 19.1.3.5, "Using count With *, identifier.*, and identifier.attr".
In the DEFINE
clause, if you apply an aggregate function to an event attribute not qualified by correlation variable, the aggregate is a running aggregate as Example 19-7 shows.
Example 19-7 Referencing Attributes not Qualified by Correlation Variable
PATTERN ((RISE FALL)+) DEFINE RISE AS count(RISE.*) = 1 or RISE.price > FALL.price, FALL AS FALL.price < RISE.price and count(*) > 1000
This query detects a pattern in which a price alternately goes up and down, for as long as possible, but for at least more than 1000 matches.
For more information, see:
The built-in aggregate function count
has syntax:
(arith_expr::=, attr::=, identifier::=)
The return value of count
depends on the argument as Table 19-1 shows.
Table 19-1 Return Values for count Aggregate Function
Consider Example 19-8. Assume that the schema of S
includes attributes account
and balance
. This query returns an event for each account
that has not received 3 or more events in 60 minutes.
Example 19-8 MATCH_RECOGNIZE Query Using count(A.*)
select T.account, T.Atime FROM S MATCH_RECOGNIZE( PARTITION BY account MEASURES A.account has account A.ELEMENT_TIME as Atime ALL MATCHES INCLUDE TIMER EVENTS PATTERN (A+) DURATION 60 MINUTES DEFINE A AS count(A.*) < 3 ) as T
The PATTERN (A+)
specifies the pattern "Match A
one or more times".
The DEFINE
clause specifies the condition:
A AS count(A.*) < 3
This condition for A
places no restrictions on input tuples (such as A.balance > 1000
). The only restrictions are imposed by the PARTITION BY account
and DURATION 60 MINUTES
clauses. In the DEFINE
clause, the A.*
means, "Match all input tuples for the group A+
". This group includes the one or more input tuples with a particular account
received in the 60 minutes starting with the first input tuple. The count(A.*)
is a running aggregate that returns the total number of events in this group.
If the DEFINE
clause specifies the condition:
A AS A.balance > 1000 and count(A.*) < 3
Then A.*
still means "Match all input tuples for the group A+
". In this case, this group includes the one or more input tuples with a particular account
received in the 60 minutes starting with the first input tuple and with balance > 1000
.
In contrast:
count(*)
means "The number of all tuples, including duplicates and nulls". That is, the number of all tuples received on S
, whether they satisfy the MATCH_RECOGNIZE
clause or not.
count(A.balance)
means "The number of all tuples that match the correlation variable A
where the balance
is not NULL
".
For more information, see:
Use the first
and last
built-in aggregate functions to access event attributes of the first or last event match, respectively:
first
returns the value of the first match of a group in the order defined by the ORDER BY
clause or the default order.
last
returns the value of the last match of a group in the order defined by the ORDER BY
clause or the default order.
The first
and last
functions accept an optional non-negative, constant integer argument (N
) that indicates the offset following the first and the offset preceding the last match of the variable, respectively. If you specify this offset, the first
function returns the N
-th matching event following the first match and the last
function returns the N
-th matching event preceding the last match. If the offset does not fall within the match of the variable, the first
and last
functions return NULL
.
For more information, see:
Use the prev
built-in single-row function to access event attributes of a previous event match. If there is no previous event match, the prev
function returns NULL
.
The prev
function accepts an optional non-negative, constant integer argument (N
) that indicates the offset to a previous match. If you specify this offset, the prev
function returns the N
-th matching event preceding the current match. If there is no such previous match, the prev
functions returns NULL
.
When you use the prev
function in the DEFINE
clause, this function may only access the currently defined correlation variable.
For example: the correlation variable definition in Example 19-9 is valid:
However, the correlation variable definition in Example 19-10 is invalid because while defining correlation variable Y
, it references correlation variable X
inside the prev
function.
For more information, see:
The MEASURES
clause exports (makes available for inclusion in the SELECT
) attribute values of events that successfully match the pattern you specify.
You may specify expressions over correlation variables that reference partition attributes, order by attributes, singleton variables and aggregates on group variables, and aggregates on the attributes of the stream that is the source of the MATCH_RECOGNIZE
clause.
You qualify attribute values by correlation variable to export the value of the attribute for the event that matches the correlation variable's condition. For example, within the MEASURES
clause, A.c1
refers to the value of event attribute c1
:
In the tuple that last matched the condition corresponding to correlation variable A
, if A
is specified in the DEFINE
clause.
In the last processed tuple, if A
is not specified in the DEFINE
clause.
This is because if A
is not specified in the DEFINE
clause, then A
is considered as TRUE
always. So effectively all the tuples in the input match to A
.
You may include in the SELECT
statement only attributes you specify in the MEASURES
clause.
(arith_expr::=, identifier::=)
In Example 19-1, the pattern_measures_clause
is:
MEASURES A.itemId as itemId
This section describes:
For more information, see:
In the MEASURES
clause, you may apply any single-row or aggregate function to the attributes of events that match a condition.
Example 19-11 applies the last
function over correlation variable Z.c1
in the MEASURES
clause.
Example 19-11 Using Functions Over Correlation Variables
<query id="tkpattern_q41"><![CDATA[ select T.firstW, T.lastZ from tkpattern_S11 MATCH_RECOGNIZE ( MEASURES A.c1 as firstW, last(Z.c1) as lastZ ALL MATCHES PATTERN(A W+ X+ Y+ Z+) DEFINE W as W.c2 < prev(W.c2), X as X.c2 > prev(X.c2), Y as Y.c2 < prev(Y.c2), Z as Z.c2 > prev(Z.c2) ) as T ]]></query>
Note the following in the MEASURES
clause in Example 19-11:
A.c1
will export the value of c1
in the first and only the first event that the query processes because:
A
is not specified in the DEFINE
clause, therefor it is always true.
A
has no pattern quantifiers, therefor it will match exactly once.
The built-in aggregate function last
will export the value of c1
in the last event that matched Z
at the time the PATTERN
clause was satisfied.
For more information, see:
The PATTERN
clause specifies the pattern to be matched as a regular expression over one ore more correlation variables.
Incoming events must match these conditions in the order given (from left to right).
The regular expression may contain correlation variables that are:
Defined in the DEFINE
clause : such correlation variables are considered true only if their condition definition evaluates to TRUE
.
Not defined in the DEFINE
clause: such correlation variables are considered as always TRUE
; that is, they match every input.
This section describes:
Section 19.3.1, "Pattern Quantifiers and Regular Expressions"
Section 19.3.2, "Grouping and Alternation in the PATTERN Clause"
For more information, see:
You express the pattern as a regular expression composed of correlation variables and pattern quantifiers.
(correlation_name::=, pattern_quantifier::=)
Table 19-2 lists the pattern quantifiers (pattern_quantifier::=) Oracle CQL supports.
Table 19-2 MATCH_RECOGNIZE Pattern Quantifiers
Maximal | Minimal | Description |
---|---|---|
0 or more times |
||
1 or more times. |
||
0 or 1 time. |
||
None |
An unquantified pattern, such as |
Use the pattern quantifiers to specify the pattern as a regular expression, such as A*
or A+?
.
The one-character pattern quantifiers are maximal or "greedy"; they will attempt to match as many instances of the regular expression on which they are applied as possible.
The two-character pattern quantifiers are minimal or "reluctant"; they will attempt to match as few instances of the regular expression on which they are applied as possible.
Consider the following pattern_clause
:
PATTERN (A B* C)
This pattern clause means a pattern match will be recognized when the following conditions are met by consecutive incoming input tuples:
Exactly one tuple matches the condition that defines correlation variable A
, followed by
Zero or more tuples that match the correlation variable B
, followed by
Exactly one tuple that matches correlation variable C
.
While in state 2, if a tuple arrives that matches both the correlation variables B
and C
(since it satisfies the defining conditions of both of them) then as the quantifier *
for B
is greedy that tuple will be considered to have matched B
instead of C
. Thus due to the greedy property B
gets preference over C
and we match a greater number of B
. Had the pattern expression be A B*? C
, one that uses a lazy or reluctant quantifier over B
, then a tuple matching both B
and C
will be treated as matching C
only. Thus C
would get preference over B
and we will match fewer B
.
For more information, see:
As shown in the regexp_grp_alt
syntax, you can use:
open and close round brackets ((
and )
) to group correlation variables
alternation operators (|
) to match either one correlation variable (or group of correlation variables) or another
(correlation_name::=, pattern_quantifier::=, regexp::=)
Consider the following pattern_clause
:
PATTERN (A+ B+)
This means "A one or more times followed by B one or more times".
You can group correlation variables. For example :
PATTERN (A+ (C+ B+)*)
This means "A one or more times followed by zero or more occurrences of C one or more times and B one or more times".
Using the PATTERN
clause alternation operator (|
), you can refine the sense of the pattern_clause
. For example:
PATTERN (A+ | B+)
This means "A one or more times or B one or more times, whichever comes first".
Similarly, you can both group correlation variables and use the alternation operator. For example:
PATTERN (A+ (C+ | B+))
This means "A one or more times followed by either C one or more times or B one or more times, whichever comes first".
To match every permutation you can use:
PATTERN ((A B) | (B A))
This means "A followed by B or B followed by A, which ever comes first".
For more information, see:
The DEFINE
clause specifies the boolean condition for each correlation variable.
You may specify any logical or arithmetic expression and apply any single-row or aggregate function to the attributes of events that match a condition.
On receiving a new tuple from the base stream, the conditions of the correlation variables that are relevant at that point in time are evaluated. A tuple is said to have matched a correlation variable if it satisfies its defining condition. A particular input can match zero, one, or more correlation variables. The relevant conditions to be evaluated on receiving an input are determined by logic governed by the PATTERN
clause regular expression and the state in pattern recognition process that we have reached after processing the earlier inputs.
The condition can refer to any of the attributes of the schema of the stream or view that evaluates to a stream on which the MATCH_RECOGNIZE
clause is being applied.
A correlation variable in the PATTERN
clause need not be specified in the DEFINE
clause: the default for such a correlation variable is a predicate that is always true. Such a correlation variable matches every event. It is an error to specify a correlation variable in the DEFINE
clause which is not used in a PATTERN
clause
No correlation variable defined by a SUBSET
clause may be defined in the DEFINE
clause.
(non_mt_corrname_definition_list::=)
non_mt_corrname_definition_list::=
(correlation_name_definition::=)
correlation_name_definition::=
(correlation_name::=, non_mt_cond_list::=)
This section describes:
Section 19.4.1, "Functions Over Correlation Variables in the DEFINE Clause"
Section 19.4.2, "Referencing Attributes in the DEFINE Clause"
Section 19.4.3, "Referencing One Correlation Variable From Another in the DEFINE Clause"
For more information, see:
You can use functions over the correlation variables while defining them.
Example 19-12 applies the to_timestamp
function to correlation variables.
Example 19-12 Using Functions Over Correlation Variables: to_timestamp
... PATTERN (A B* C) DEFINE A AS (A.temp >= 25), B AS ((B.temp >= 25) and (to_timestamp(B.element_time) - to_timestamp(A.element_time) < INTERVAL "0 00:00:05.00" DAY TO SECOND)), C AS (to_timestamp(C.element_time) - to_timestamp(A.element_time) >= INTERVAL "0 00:00:05.00" DAY TO SECOND) ...
Example 19-13 applies the count
function to correlation variable B
to count the number of times its definition was satisfied. A match is recognized when totalCountValue
is less than 1000 two or more times in 30 minutes.
Example 19-13 Using Functions Over Correlation Variables: count
... MATCH_RECOGNIZE( ... PATTERN(B*) DURATION 30 MINUTES DEFINE B as (B.totalCountValue < 1000 and count(B.*) >= 2) ...
For more information, see:
You can refer to the attributes of a base stream:
Without a correlation variable: c1 < 20
.
With a correlation variable: A.c1 < 20
.
When you refer to the attributes without a correlation variable, a tuple that last matched any of the correlation variables is consulted for evaluation.
Consider the following definitions:
DEFINE A as c1 < 20
DEFINE A as A.c1 < 20
Both refer to c1
in the same tuple which is the latest input tuple. This is because on receiving an input we evaluate the condition of a correlation variable assuming that the latest input matches that correlation variable.
If you specify a correlation name that is not defined in the DEFINE
clause, it is considered to be true for every input.
In Example 19-14, correlation variable A
appears in the PATTERN
clause but is not specified in the DEFINE
clause. This means the correlation name A
is true for every input. It is an error to define a correlation name which is not used in a PATTERN
clause.
Example 19-14 Undefined Correlation Name
<query id="q"><![CDATA[ SELECT T.firstW, T.lastZ FROM S2 MATCH_RECOGNIZE ( MEASURES A.c1 as firstW, last(Z) as lastZ PATTERN(A W+ X+ Y+ Z+) DEFINE W as W.c2 < prev(W.c2), X as X.c2 > prev(X.c2), Y as Y.c2 < prev(Y.c2), Z as Z.c2 > prev(Z.c2) ) as T ]]></query>
For more information, see:
A definition of one correlation variable can refer to another correlation variable. Consider the query that Example 19-15 shows:
Example 19-15 Referencing One Correlation Variable From Another
... Select a_firsttime, d_lasttime, b_avgprice, d_avgprice FROM S MATCH_RECOGNIZE ( PARTITION BY symbol MEASURES first(a.time) as a_firsttime, last(d.time) as d_lasttime, avg(b.price) as b_avgprice, avg(d.price) as d_avgprice PATTERN (A B+ C+ D) DEFINE A as A.price > 100, B as B.price > A.price, C as C.price < avg(B.price), D as D.price > prev(D.price) ) ...
Note the following:
Because correlation variable A
defines a single attribute, B
can refer to this single attribute.
Because B
defines more than one attribute, C
cannot reference a single attribute of B
. In this case, C
may only reference an aggregate of B
.
D
is defined in terms of itself: in this case, you may refer to a single attribute or an aggregate. In this example, the prev
function is used to access the match of D
prior to the current match.
For more information, see:
Use this optional clause to specify the stream attributes by which a MATCH_RECOGNIZE
clause should partition its results.
Without a PARTITION BY
clause, all stream attributes belong to the same partition.
In Example 19-1, the pattern_partition_clause
is:
PARTITION BY itemId
The partition by clause in pattern means the input stream is logically divided based on the attributes mentioned in the partition list and pattern matching is done within a partition.
Consider a stream S
with schema (c1 integer, c2 integer)
with the input data that Example 19-16 shows.
Consider the MATCH_RECOGNIZE
query that Example 19-17 shows.
Example 19-17 MATCH_RECOGNIZE Query Using Input Stream S1
select T.p1, T.p2, T.p3 from S MATCH_RECOGNIZE( MEASURES A.ELEMENT_TIME as p1, B.ELEMENT_TIME as p2 B.c2 as p3 PATTERN (A B) DEFINE A as A.c1 = 10, B as B.c1 = 20 ) as T
This query would output the following:
3000:+ 2000, 3000, 2
If we add PARTITION BY c2
to the query that Example 19-17 shows, then the output would change to:
3000:+ 2000, 3000, 2 4000:+ 1000, 4000, 1
This is because by adding the PARTITION BY
clause, matches are done within partition only. Tuples at 1000 and 4000 belong to one partition and tuples at 2000 and 3000 belong to another partition owing to the value of c2
attribute in them. In the first partition A
matches tuple at 1000 and B
matches tuple at 4000. Even though a tuple at 3000 matches the B
definition, it is not presented as a match for the first partition since that tuple belongs to different partition.
When you partition by more than one attribute, you can control the order of partitions using the ORDER BY
clause. For more information, see Section 19.6, "ORDER BY Clause".
Use this optional clause to specify the stream attributes by which a MATCH_RECOGNIZE
clause should order partitions when using a PARTITION BY
clause.
Without an ORDER BY
clause, the results of MATCH_RECOGNIZE
are nondeterministic.
pattern_order_by_top_clause::=
You may only use the ORDER BY
clause with a PARTITION BY
clause.
For more information, see Section 19.5, "PARTITION BY Clause,"pattern_partition_clause::=, and order_by_list::=.
Use this optional clause to configure Oracle CEP to match overlapping patterns.
With the ALL MATCHES
clause, Oracle CEP finds all possible matches. Matches may overlap and may start at the same event. In this case, there is no distinction between greedy and reluctant pattern quantifiers. For example, the following pattern:
ALL MATCHES PATTERN (A* B)
produces the same result as:
ALL MATCHES PATTERN (A*? B)
Without the ALL MATCHES
clause, overlapping matches are not returned, and quantifiers such as the asterisk determine which among a set of candidate (and overlapping) matches is the preferred one for output. The rest of the overlapping matches are discarded.
Consider the query tkpattern_q41
in Example 19-18 that uses ALL MATCHES
and the data stream tkpattern_S11
in Example 19-19. Stream tkpattern_S11
has schema (c1 integer, c2 integer)
. The query returns the stream in Example 19-20.
The query tkpattern_q41
in Example 19-18 will report a match when the input stream values, when plotted, form the shape of the English letter W. The relation in Example 19-20 shows an example of overlapping instances of this W-pattern match.
There are two types of overlapping pattern instances:
Total: Example of total overlapping: Rows from time 3000-9000 and 4000-9000 in the input, both match the given pattern expression. Here the longest one (3000-9000) will be preferred if ALL MATCHES
clause is not present.
Partial: Example of Partial overlapping: Rows from time 12000-21000 and 16000-23000 in the input, both match the given pattern expression. Here the one which appears earlier is preferred when ALL MATCHES
clause is not present. This is because when ALL MATCHES
clause is omitted, we start looking for the next instance of pattern match at a tuple which is next to the last tuple in the previous matched instance of the pattern.
Example 19-18 ALL MATCHES Clause Query
<query id="tkpattern_q41"><![CDATA[ select T.firstW, T.lastZ from tkpattern_S11 MATCH_RECOGNIZE ( MEASURES A.c1 as firstW, last(Z.c1) as lastZ ALL MATCHES PATTERN(A W+ X+ Y+ Z+) DEFINE W as W.c2 < prev(W.c2), X as X.c2 > prev(X.c2), Y as Y.c2 < prev(Y.c2), Z as Z.c2 > prev(Z.c2) ) as T ]]></query>
Example 19-19 ALL MATCHES Clause Stream Input
Timestamp Tuple 1000 1,8 2000 2,8 3000 3,8 4000 4,6 5000 5,3 6000 6,7 7000 7,6 8000 8,2 9000 9,6 10000 10,2 11000 11,9 12000 12,9 13000 13,8 14000 14,5 15000 15,0 16000 16,9 17000 17,2 18000 18,0 19000 19,2 20000 20,3 21000 21,8 22000 22,5 23000 23,9 24000 24,9 25000 25,4 26000 26,7 27000 27,2 28000 28,8 29000 29,0 30000 30,4 31000 31,4 32000 32,7 33000 33,8 34000 34,6 35000 35,4 36000 36,5 37000 37,1 38000 38,7 39000 39,5 40000 40,8 41000 41,6 42000 42,6 43000 43,0 44000 44,6 45000 45,8 46000 46,4 47000 47,3 48000 48,8 49000 49,2 50000 50,5 51000 51,3 52000 52,3 53000 53,9 54000 54,8 55000 55,5 56000 56,5 57000 57,9 58000 58,7 59000 59,3 60000 60,3
Example 19-20 ALL MATCHES Clause Stream Output
Timestamp Tuple Kind Tuple 9000: + 3,9 9000: + 4,9 11000: + 6,11 11000: + 7,11 19000: + 12,19 19000: + 13,19 19000: + 14,19 20000: + 12,20 20000: + 13,20 20000: + 14,20 21000: + 12,21 21000: + 13,21 21000: + 14,21 23000: + 16,23 23000: + 17,23 28000: + 24,28 30000: + 26,30 38000: + 33,38 38000: + 34,38 40000: + 36,40 48000: + 42,48 50000: + 45,50 50000: + 46,50
As Example 19-20 shows, the ALL MATCHES
clause reports all the matched pattern instances on receiving a particular input. For example, at time 20000, all of the tuples {12,20}
, {13,20}
, and {14,20}
are output.
For more information, see Section 19.3.1, "Pattern Quantifiers and Regular Expressions".
The WITHIN
clause is an optional clause that outputs a pattern_clause
match if and only if the match occurs within the specified time duration.
That is, if and only if:
TL - TF < WD
Where:
TL
- Timestamp of last event matching the pattern.
TF
- Timestamp of first event matching the pattern.
WD
- Duration specified in the WITHIN
clause.
The WITHIN INCLUSIVE
clause tries to match events at the boundary case as well. That is, it outputs a match if and only if:
TL - TF <= WD
If the match completes within the specified time duration, then the event is output as soon as it happens. That is, if the match can be output, it is output with the timestamp at which it completes. The WITHIN
clause does not wait for the time duration to expire as the DURATION
clause does.
When the WITHIN
clause duration expires, it discards any potential candidate matches which are incomplete.
For more information, see Section 19.12.4, "Pattern Detection With the WITHIN Clause".
Note:
You cannot use aWITHIN
clause with a DURATION
clause. For more information, see Section 19.9, "DURATION Clause".The DURATION
clause is an optional clause that you should use only when writing a query involving non-event detection. Non-event detection is the detection of a situation when a certain event which should have occurred in a particular time limit does not occur in that time frame.
Using this clause, a match is reported only when the regular expression in the PATTERN
clause is matched completely and no other event or input arrives until the duration specified in the DURATION
clause expires. The duration is measured from the time of arrival of the first event in the pattern match.
You must use the INCLUDE TIMER EVENTS
clause when using the DURATION
clause. For more information, see Section 19.10, "INCLUDE TIMER EVENTS Clause".
This section describes:
Note:
You cannot use aDURATION
clause with a WITHIN
clause. For more information, see Section 19.8, "WITHIN Clause".The duration can be specified as a constant value, such as 10. Optionally, you may specify a time unit such as seconds or minutes (see time_unit::=); the default time unit is seconds.
Consider the query tkpattern_q59
in Example 19-21 that uses DURATION 10
to specify a delay of 10 s (10000 ms) and the data stream tkpattern_S19
in Example 19-22. Stream tkpattern_S19
has schema (c1 integer)
. The query returns the stream in Example 19-23.
Example 19-21 MATCH_RECOGNIZE with Fixed Duration DURATION Clause Query
<query id="BBAQuery"><![CDATA[ select T.p1, T.p2 from tkpattern_S19 MATCH_RECOGNIZE ( MEASURES A.c1 as p1, B.c1 as p2 include timer events PATTERN(A B*) duration 10 DEFINE A as A.c1 = 10, B as B.c1 != A.c1 ) as T ]]></query>
Example 19-22 MATCH_RECOGNIZE with Fixed Duration DURATION Clause Stream Input
Timestamp Tuple 1000 10 4000 22 6000 444 7000 83 9000 88 11000 12 11000 22 11000 15 12000 13 15000 10 27000 11 28000 10 30000 18 40000 10 44000 19 52000 10 h 100000
Example 19-23 MATCH_RECOGNIZE with Fixed DURATION Clause Stream Output
Timestamp Tuple Kind Tuple 11000: + 10,88 25000: + 10, 38000: + 10,18 50000: + 10,19 62000: + 10,
The tuple at time 1000 matches A
.
Since the duration is 10 we output a match as soon as input at time 1000+10000=11000
is received (the one with the value 12). Since the sequence of tuples from 1000 through 9000 match the pattern AB*
and nothing else a match is reported as soon as input at time 11000 is received.
The next match starts at 15000 with the tuple at that time matching A
. The next tuple that arrives is at 27000. So here also we have tuples satisfying pattern AB*
and nothing else and hence a match is reported at time 15000+10000=25000
. Further output is generated by following similar logic.
For more information, see "Fixed Duration Non-Event Detection".
When you specify a MULTIPLES OF
clause, it indicates recurring non-event detection. In this case an output is sent at the multiples of duration value as long as there is no event after the pattern matches completely.
Consider the query tkpattern_q75
in Example 19-24 that uses DURATION MULTIPLES OF 10
to specify a delay of 10 s (10000 ms) and the data stream tkpattern_S23
in Example 19-25. Stream tkpattern_S23
has schema (c1 integer)
. The query returns the stream in Example 19-26.
Example 19-24 MATCH_RECOGNIZE with Variable Duration DURATION MULTIPLES OF Clause Query
<query id="tkpattern_q75"><![CDATA[ select T.p1, T.p2, T.p3 from tkpattern_S23 MATCH_RECOGNIZE ( MEASURES A.c1 as p1, B.c1 as p2, sum(B.c1) as p3 ALL MATCHES include timer events PATTERN(A B*) duration multiples of 10 DEFINE A as A.c1 = 10, B as B.c1 != A.c1 ) as T ]]></query>
Example 19-25 MATCH_RECOGNIZE with Variable Duration DURATION MULTIPLES OF Clause Stream Input
Timestamp Tuple 1000 10 4000 22 6000 444 7000 83 9000 88 11000 12 11000 22 11000 15 12000 13 15000 10 27000 11 28000 10 30000 18 44000 19 62000 20 72000 10 h 120000
Example 19-26 MATCH_RECOGNIZE with Variable Duration DURATION MULTIPLES OF Clause Stream Output
Timestamp Tuple Kind Tuple 11000: + 10,88,637 25000: + 10,, 38000: + 10,18,18 48000: + 10,19,37 58000: + 10,19,37 68000: + 10,20,57 82000: + 10,, 92000: + 10,, 102000: + 10,, 112000: + 10,,
The execution here follows similar logic to that of the example above for just the DURATION
clause (see "Fixed Duration Non-Event Detection"). The difference comes for the later outputs. The tuple at 72000 matches A
and then there is nothing else after that. So the pattern AB*
is matched and we get output at 82000. Since we have the MULTIPLES OF
clause and duration 10 we see outputs at time 92000, 102000, and so on.
Use this clause in conjunction with the DURATION
clause for non-event detection queries.
Typically, in most pattern match queries, a pattern match output is always triggered by an input event on the input stream over which pattern is being matched. The only exception is non-event detection queries where there could be an output triggered by a timer expiry event (as opposed to an explicit input event on the input stream).
pattern_inc_timer_evs_clause::=
(pattern_clause::=, pattern_skip_match_clause::=, pattern_definition_clause::=, duration_clause::=, subset_clause::=)
For more information, see Section 19.9, "DURATION Clause".
Using this clause, you can group together one or more correlation variables that are defined in the DEFINE
clause. You can use this named subset in the MEASURES
and DEFINE
clauses just like any other correlation variable.
For example:
SUBSET S1 = (Z,X)
The right-hand side of the subset ((Z,X)
) is a comma-separated list of one or more correlation variables as defined in the PATTERN
clause.
The left-hand side of the subset (S1
) is the union of the correlation variables on the right-hand side.
You cannot include a subset variable in the right-hand side of a subset.
(non_mt_subset_definition_list::=)
non_mt_subset_definition_list::=
(subset_name::=, non_mt_corr_list::=)
Consider the query q55
in Example 19-27 and the data stream S11
in Example 19-28. Stream S11
has schema (c1 integer, c2 integer)
. This example defines subsets S1
through S6
. This query outputs a match if the c2
attribute values in the input stream form the shape of the English letter W. Now suppose we want to know the sum of the values of c2
for those tuples which form the incrementing arms of this W shape. The correlation variable X
represents tuples that are part of the first incrementing arm and Z
represent the tuples that are part of the second incrementing arm. So we need some way to group the tuples that match both. Such a requirement can be captured by defining a SUBSET
clause as the example shows.
Subset S4
is defined as (X,Z)
. It refers to the tuples in the input stream that match either X
or Z
. This subset is used in the MEASURES
clause statement sum(S4.c2) as sumIncrArm
. This computes the sum of the value of c2
attribute in the tuples that match either X
or Z
. A reference to S4.c2
in a DEFINE
clause like S4.c2 = 10
will refer to the value of c2
in the latest among the last tuple that matched X
and the last tuple that matched Z
.
Subset S6
is defined as (Y)
. It refers to all the tuples that match correlation variable Y
.
The query returns the stream in Example 19-29.
Example 19-27 MATCH_RECOGNIZE with SUBSET Clause Query
<query id="q55"><![CDATA[ select T.firstW, T.lastZ, T.sumDecrArm, T.sumIncrArm, T.overallAvg from S11 MATCH_RECOGNIZE ( MEASURES S2.c1 as firstW, last(S1.c1) as lastZ, sum(S3.c2) as sumDecrArm, sum(S4.c2) as sumIncrArm, avg(S5.c2) as overallAvg PATTERN(A W+ X+ Y+ Z+) SUBSET S1 = (Z) S2 = (A) S3 = (A,W,Y) S4 = (X,Z) S5 = (A,W,X,Y,Z) S6 = (Y) DEFINE W as W.c2 < prev(W.c2), X as X.c2 > prev(X.c2), Y as S6.c2 < prev(Y.c2), Z as Z.c2 > prev(Z.c2) ) as T ]]></query>
Example 19-28 MATCH_RECOGNIZE with SUBSET Clause Stream Input
Timestamp Tuple 1000 1,8 2000 2,8 3000 3,8 4000 4,6 5000 5,3 6000 6,7 7000 7,6 8000 8,2 9000 9,6 10000 10,2 11000 11,9 12000 12,9 13000 13,8 14000 14,5 15000 15,0 16000 16,9 17000 17,2 18000 18,0 19000 19,2 20000 20,3 21000 21,8 22000 22,5 23000 23,9 24000 24,9 25000 25,4 26000 26,7 27000 27,2 28000 28,8 29000 29,0 30000 30,4 31000 31,4 32000 32,7 33000 33,8 34000 34,6 35000 35,4 36000 36,5 37000 37,1 38000 38,7 39000 39,5 40000 40,8 41000 41,6 42000 42,6 43000 43,0 44000 44,6 45000 45,8 46000 46,4 47000 47,3 48000 48,8 49000 49,2 50000 50,5 51000 51,3 52000 52,3 53000 53,9 54000 54,8 55000 55,5 56000 56,5 57000 57,9 58000 58,7 59000 59,3 60000 60,3
Example 19-29 MATCH_RECOGNIZE with SUBSET Clause Stream Output
Timestamp Tuple Kind Tuple 9000: + 3,9,25,13,5.428571 21000: + 12,21,24,22,4.6 28000: + 24,28,15,15,6.0 38000: + 33,38,19,12,5.1666665 48000: + 42,48,13,22,5.0
For more information, see:
The following examples illustrate basic MATCH_RECOGNIZE
practices:
For more examples, see Oracle Complex Event Processing Getting Started.
Consider the stock fluctuations that Figure 19-1 shows. This data can be represented as a stream of stock ticks (index number or time) and stock price. Figure 19-1 shows a common trading behavior known as a double bottom pattern between days 1 and 9 and between days 12 and 19. This pattern can be visualized as a W-shaped change in stock price: a fall (X
), a rise (Y
), a fall (W
), and another rise (Z
).
Figure 19-1 Pattern Detection: Double Bottom Stock Fluctuations
Example 19-30 shows a query q
on stream S2
of stock price events with schema symbol
, stockTick
, and price
. This query detects double bottom patterns on the incoming stock trades using the PATTERN
clause (A W+ X+ Y+ Z+
). The correlation names in this clause are:
A
: corresponds to the start point of the double bottom pattern.
Because correlation name A
is true for every input, it is not defined in the DEFINE
clause. If you specify a correlation name that is not defined in the DEFINE
clause, it is considered to be true for every input.
W
+: corresponds to the first decreasing arm of the double bottom pattern.
It is defined by W.price < prev(W.price)
. This definition implies that the current price is less than the previous one.
X+
: corresponds to the first increasing arm of the double bottom pattern.
Y+
: corresponds to the second decreasing arm of the double bottom pattern.
Z+
: corresponds to the second increasing arm of the double bottom pattern.
Example 19-30 Simple Pattern Detection: Query
<query id="q"><![CDATA[ SELECT T.firstW, T.lastZ FROM S2 MATCH_RECOGNIZE ( MEASURES A.stockTick as firstW, last(Z) as lastZ PATTERN(A W+ X+ Y+ Z+) DEFINE W as W.price < prev(W.price), X as X.price > prev(X.price), Y as Y.price < prev(Y.price), Z as Z.price > prev(Z.price) ) as T WHERE S2.symbol = "oracle" ]]></query>
Consider the stock fluctuations that Figure 19-2 shows. This data can be represented as a stream of stock ticks (index number or time) and stock price. In this case, the stream contains data for more than one stock ticker symbol. Figure 19-2 shows a common trading behavior known as a double bottom pattern between days 1 and 9 and between days 12 and 19 for stock BOFA. This pattern can be visualized as a W-shaped change in stock price: a fall (X
), a rise (Y
), a fall (W
), and another rise (Z
).
Figure 19-2 Pattern Detection With Partition By: Stock Fluctuations
Example 19-31 shows a query q
on stream S2
of stock price events with schema symbol
, stockTick
, and price
. This query detects double bottom patterns on the incoming stock trades using the PATTERN
clause (A W+ X+ Y+ Z+
). The correlation names in this clause are:
A
: corresponds to the start point of the double bottom pattern.
W
+: corresponds to the first decreasing arm of the double bottom pattern as defined by W.price < prev(W.price)
, which implies that the current price is less than the previous one.
X+
: corresponds to the first increasing arm of the double bottom pattern.
Y+
: corresponds to the second decreasing arm of the double bottom pattern.
Z+
: corresponds to the second increasing arm of the double bottom pattern.
The query partitions the input stream by stock ticker symbol using the PARTITION BY
clause and applies this PATTERN
clause to each logical stream.
Example 19-31 Pattern Detection With PARTITION BY: Query
<query id="q"><![CDATA[ SELECT T.firstW, T.lastZ FROM S2 MATCH_RECOGNIZE ( PARTITION BY A.symbol MEASURES A.stockTick as firstW, last(Z) as lastZ PATTERN(A W+ X+ Y+ Z+) DEFINE W as W.price < prev(W.price), X as X.price > prev(X.price), Y as Y.price < prev(Y.price), Z as Z.price > prev(Z.price) ) as T ]]></query>
Consider the query q1
in Example 19-32 and the data stream S
in Example 19-33. Stream S
has schema (c1 integer)
. The query returns the stream in Example 19-34.
Example 19-32 Pattern Detection With Aggregates: Query
<query id="q1"><![CDATA[ SELECT T.sumB FROM S MATCH_RECOGNIZE ( MEASURES sum(B.c1) as sumB PATTERN(A B* C) DEFINE A as ((A.c1 < 50) AND (A.c1 > 35)), B as B.c1 > avg(A.c1), C as C.c1 > prev(C.c1) ) as T ]]></query>
Consider the queries in Example 19-35 and Example 19-36 and the data stream S
in Example 19-37. Stream S
has schema (c1 integer, c2 integer)
. Table 19-3 compares the output of these queries.
Example 19-35 PATTERN Clause and WITHIN Clause
<query id="queryWithin"><![CDATA[
SELECT T.Ac2, T.Bc2, T.Cc2
FROM S
MATCH_RECOGNIZE(
MEASURES A.c2 as Ac2, B.c2 as Bc2, C.c2 as Cc2
PATTERN (A (B+ | C)) within 3000 milliseconds
DEFINE
A as A.c1=10 or A.c1=25,
B as B.c1=20 or B.c1=15 or B.c1=25,
C as C.c1=15
) as T
]]></query>
Example 19-36 PATTERN Clause and WITHIN INCLUSIVE Clause
<query id="queryWithinInclusive"><![CDATA[
SELECT T.Ac2, T.Bc2, T.Cc2
FROM S
MATCH_RECOGNIZE(
MEASURES A.c2 as Ac2, B.c2 as Bc2, C.c2 as Cc2
PATTERN (A (B+ | C)) within inclusive 3000 milliseconds
DEFINE
A as A.c1=10 or A.c1=25,
B as B.c1=20 or B.c1=15 or B.c1=25,
C as C.c1=15
) as T
]]></query>
Example 19-37 Pattern Detection With the WITHIN Clause: Stream Input
Timestamp Tuple 1000 10,100 h 2000 3000 15,200 3000 20,300 4000 25,400 5000 20,500 6000 20,600 7000 35,700 8000 10,800 9000 15,900 h 11000 11000 20,1000 11000 50,1100
Table 19-3 WITHIN and WITHIN INCLUSIVE Query Output
Query queryWithin | Query queryWithinInclusive |
---|---|
Timestamp Tuple Kind Tuple 3000: + 100,300, 6000: + 400,600, 9000: + 800,900, |
Timestamp Tuple Kind Tuple 4000: + 100,400, 11000: + 800,1000, |
As Table 19-3 shows for the queryWithin
query, the candidate match starts with the event at TimeStamp=1000
and since the WITHIN
clause duration is 3 seconds, the query will output the match only if it completes before the event at TimeStamp=4000
. When the query receives the event at TimeStampe=4000
, the longest match up to that point (since we are not using ALL MATCHES
) is output. Note that although the event at TimeStamp=4000
matches B
, it is not included in the match. The next match starts with the event at TimeStamp=4000
since that event also matches A
and the previous match ends at TimeStamp=3000
.
As Table 19-3 shows for the queryWithinInclusive
query, the candidate match starts with the event at TimeStamp=1000
. When the query receives the event at TimeStamp=4000
, that event is included in the match because the query uses WITHIN INCLUSIVE
and the event matches B
. Note that although the event at TimeStamp=5000
matches B
, the pattern is not grown further since it exceeds the duration (3 seconds) measured from the start of the match (TimeStamp=1000
). Since this match ends at TimeStamp=4000
and we are not using ALL MATCHES
, the next match does not start at TimeStamp=4000
, even though it matches A
.
For more information, see:
Consider an object that moves among five different rooms. Each time it starts from room 1, it must reach room 5 within 5 minutes. Figure 19-3 shows the object's performance. This data can be represented as a stream of time and room number. Note that when the object started from room 1 at time 1, it reached room 5 at time 5, as expected. However, when the object started from room 1 at time 6, it failed to reach room 5 at time 11; it reached room 5 at time 12. When the object started from room 1 at time 15, it was in room 5 at time 20, as expected. However, when the object started from room 1 at time 23, it failed to reach room 5 at time 28; it reached room 5 at time 30. The successes at times 5 and 20 are considered events: the arrival of the object in room 5 at the appropriate time. The failures at time 11 and 28 are considered non-events: the expected arrival event did not occur. Using Oracle CQL, you can query for such non-events.
Figure 19-3 Fixed Duration Non-Event Detection
Example 19-38 shows query q
on stream S
(with schema c1
integer representing room number) that detects these non-events. Each time the object fails to reach room 5 within 5 minutes of leaving room 1, the query returns the time of departure from room 1.
Example 19-38 Fixed Duration Non-Event Detection: Query
<query id="q"><![CDATA[ select T.Atime FROM S MATCH_RECOGNIZE( MEASURES A.ELEMENT_TIME as Atime INCLUDE TIMER EVENTS PATTERN (A B*) DURATION 5 MINUTES DEFINE A as A.c1 = 1, B as B.c1 != 5 ) as T ]]></query>
For more information, see Section 19.9, "DURATION Clause".