SlideShare a Scribd company logo
1 of 206
Download to read offline
Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |
bienvenido
Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |
Lo siento, no hablo español :-(
Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |
But I will do my best to help
Pero haré todo lo posible para ayudar
Pattern Matching
Connor McDonald
Database Advocate
La coincidencia de patrones
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
Connor McDonald
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
6
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
7
Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |
Me
youtube bit.ly/youtube-connor
blog bit.ly/blog-connor
twitter bit.ly/twitter-connor
400+ posts mainly on database & development
250 technical videos, new uploads every week
Más de 400 publicaciones principalmente en bases de datos y desarrollo
250 videos técnicos, nuevas cargas cada semana
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
etc...
facebook bit.ly/facebook-connor
linkedin bit.ly/linkedin-connor
instagram bit.ly/instagram-connor
slideshare bit.ly/slideshare-connor
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
10https://asktom.oracle.com
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
https://asktom.oracle.com/officehours
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
12
SQL> lots and lots and lots of code :-)
SQL> mucho mucho mucho código
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
classical problem
13
problema clásico
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select deptno, ename
2 from emp
3 order by 1,2;
DEPTNO ENAME
---------- ----------
10 CLARK
10 KING
10 MILLER
20 ADAMS
20 FORD
20 JONES
20 SCOTT
20 SMITH
30 ALLEN
30 BLAKE
30 JAMES
30 MARTIN
30 TURNER
30 WARD
14
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
DEPTNO MEMBERS
---------- -------------------------------------
10 CLARK,KING,MILLER
20 SMITH,JONES,SCOTT,ADAMS,FORD
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
15
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
how we used to do it
16
como solíamos hacerlo
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select deptno , rtrim(ename,',') enames
2 from ( select deptno,ename,rn
3 from emp
4 model
5 partition by (deptno)
6 dimension by (
7 row_number() over
8 (partition by deptno order by ename) rn
9 )
10 measures (cast(ename as varchar2(40)) ename)
11 rules
12 ( ename[any]
13 order by rn desc = ename[cv()]||','||ename[cv()+1])
14 )
15 where rn = 1
16 order by deptno;
DEPTNO ENAMES
---------- ----------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
17
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select deptno,
2 substr(max(sys_connect_by_path(ename, ',')), 2) members
3 from (select deptno, ename,
4 row_number ()
5 over (partition by deptno order by empno) rn
6 from emp)
7 start with rn = 1
8 connect by prior rn = rn - 1
9 and prior deptno = deptno
10 group by deptno
11 /
DEPTNO MEMBERS
---------- ---------------------------------------------------------
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
20 SMITH,JONES,SCOTT,ADAMS,FORD
10 CLARK,KING,MILLER
18
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select deptno,
2 xmltransform
3 ( sys_xmlagg
4 ( sys_xmlgen(ename)
5 ),
6 xmltype
7 (
8 '<?xml version="1.0"?><xsl:stylesheet version="1.0"
9 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
10 <xsl:template match="/">
11 <xsl:for-each select="/ROWSET/ENAME">
12 <xsl:value-of select="text()"/>,</xsl:for-each>
13 </xsl:template>
14 </xsl:stylesheet>'
15 )
16 ).getstringval() members
17 from emp
18 group by deptno;
DEPTNO MEMBERS
---------- --------------------------------------------------------
10 CLARK,MILLER,KING,
20 SMITH,FORD,ADAMS,SCOTT,JONES,
30 ALLEN,JAMES,TURNER,BLAKE,MARTIN,WARD,
19
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> create or replace type string_agg_type as object
2 (
3 total varchar2(4000),
4
5 static function
6 ODCIAggregateInitialize(sctx IN OUT string_agg_type )
7 return number,
8
9 member function
10 ODCIAggregateIterate(self IN OUT string_agg_type ,
11 value IN varchar2 )
12 return number,
13
14 member function
15 ODCIAggregateTerminate(self IN string_agg_type,
16 returnValue OUT varchar2,
17 flags IN number)
18 return number,
19
20 member function
21 ODCIAggregateMerge(self IN OUT string_agg_type,
22 ctx2 IN string_agg_type)
23 return number
24 );
25 /
20
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
11g
21
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select deptno,
2 listagg( ename, ',')
3 within group (order by empno) members
4 from emp
5 group by deptno;
DEPTNO MEMBERS
---------- -----------------------------------------
10 CLARK,KING,MILLER
20 SMITH,JONES,SCOTT,ADAMS,FORD
30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES
22
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
question
solution
23
pregunta
solución
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select deptno,
2 listagg( ename, ',')
3 within group (order by empno) members
4 from emp
5 group by deptno;
24
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
still challenges
25
todavía hay desafíos
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
example
26
ejemplo
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 27
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
28
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"I want to reward active customers…
If their transaction volume grows by 20% in a day,
or grows by 10% for 2 consecutive days,
then show me their details"
29
"Quiero recompensar a los clientes activos ...
Si su volumen de transacciones crece un 20% en un día,
o crece un 10% durante 2 días consecutivos,
entonces muéstrame sus detalles "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from cust_summary
2 order by 1,2;
CUSTOMER DTE TXN_CNT
------------------------------ --------- ----------
Gerald Jones 06-FEB-17 100
Gerald Jones 07-FEB-17 130
Gerald Jones 08-FEB-17 145
Gerald Jones 09-FEB-17 200
Gerald Jones 10-FEB-17 225
Gerald Jones 11-FEB-17 255
Gerald Jones 12-FEB-17 285
Gerald Jones 13-FEB-17 315
John Smith 01-FEB-17 100
John Smith 02-FEB-17 103
John Smith 03-FEB-17 116
John Smith 04-FEB-17 129
John Smith 05-FEB-17 142
Sue Brown 06-FEB-17 50
Sue Brown 07-FEB-17 53
Sue Brown 08-FEB-17 72
...
30
20% in a day
10% each day
over 2 days
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 31
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
analytics
32
analítica
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select row_number() OVER ( order by sal )
2 from emp
3 ...
33
https://bit.ly/analytic_sql
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"I want to reward active customers…
If their transaction volume grows by 20% in a day,
or grows by 10% for 2 consecutive days,
then show me the details"
34
En un día
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn
2 from (
3 select customer, dte, cumu_txns
4 , lead(cumu_txns) over (
5 partition by customer order by dte
6 ) next_txn
7 from cust_summary
8 );
CUSTOMER DTE CUMU_TXNS NEXT_TXN DAILY_TXN
------------------------------ --------- ---------- ---------- ----------
Gerald Jones 06-FEB-17 100 130 30
Gerald Jones 07-FEB-17 130 145 15
Gerald Jones 08-FEB-17 145 200 55
Gerald Jones 09-FEB-17 200 225 25
Gerald Jones 10-FEB-17 225 255 30
35
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"I want to reward active customers…
If their transaction volume grows by 20% in a day,
or grows by 10% for 2 consecutive days,
then show me the details"
36
crece un 20% en un día,
o crece en un 10%
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn
2 , case
3 when next_txn >= cumu_txns * 1.20 then 'FAST'
4 when next_txn >= cumu_txns * 1.10 then 'SLOW'
5 end growth_class
6 from (
7 select customer, dte, cumu_txns
8 , lead(cumu_txns) over (
9 partition by customer order by dte
10 ) next_txn
11 from cust_summary
12 );
CUSTOMER DTE CUMU_TXNS NEXT_TXN DAILY_TXN GROWTH_CLASS
------------------------------ --------- ---------- ---------- ---------- ------------
Gerald Jones 06-FEB-17 100 130 30 FAST
Gerald Jones 07-FEB-17 130 145 15 SLOW
Gerald Jones 08-FEB-17 145 200 55 FAST
Gerald Jones 09-FEB-17 200 225 25 SLOW
Gerald Jones 10-FEB-17 225 255 30 SLOW
Gerald Jones 11-FEB-17 255 285 30 SLOW
Gerald Jones 12-FEB-17 285 315 30 SLOW
37
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"I want to reward active customers…
If their transaction volume grows by 20% in a day,
or grows by 10% for 2 consecutive days,
then show me the details"
38
2 días consecutivos
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, dte, cumu_txns, next_txn, daily_txn
2 , case
3 when growth_class is not null and
4 ( lag(growth_class) over (
5 partition by customer order by dte
6 ) is null
7 or
8 lag(growth_class) over (
9 partition by customer order by dte
10 ) != growth_class
11 )
12 then dte
13 end growthstartdate
14 from (
15 select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn
16 , case
17 when next_txn >= cumu_txns * 1.20 then 'FAST'
18 when next_txn >= cumu_txns * 1.10 then 'SLOW'
19 end growth_class
20 from (
21 select customer, dte, cumu_txns
22 , lead(cumu_txns) over (
23 partition by customer order by dte
24 ) next_txn
25 from cust_summary
26 ) )
39
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, dte, cumu_txns, next_txn, daily_txn
2 , last_value(growthstartdate ignore nulls) over (
3 partition by customer, growth_class order by dte
4 rows between unbounded preceding and current row
5 ) startdate
6 from (
7 select customer, growth_class, dte, cumu_txns, next_txn, daily_txn
8 , case
9 when growth_class is not null and
10 ( lag(growth_class) over (
11 partition by customer order by dte ) is null or
12 lag(growth_class) over (
13 partition by customer order by dte
14 ) != growth_class )
15 then dte
16 end growthstartdate
17 from (
18 select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn
19 , case when next_txn >= cumu_txns * 1.20 then 'FAST'
20 when next_txn >= cumu_txns * 1.10 then 'SLOW'
21 end growth_class
22 from (
23 select customer, dte, cumu_txns
24 , lead(cumu_txns) over (partition by customer order by dte
25 ) next_txn
26 from cust_summary
27 ) ) )
28 where growth_class is not null
40
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate
2 , min(cumu_txns) keep (dense_rank first order by dte) start_txn
3 , max(dte) enddate
4 , max(next_txn) keep (dense_rank last order by dte) end_txn
5 , avg(daily_txn) avg_daily_txn
6 from (
7 select customer, growth_class, dte, cumu_txns, next_txn, daily_txn
8 , last_value(growthstartdate ignore nulls) over (
9 partition by customer, growth_class order by dte
10 rows between unbounded preceding and current row
11 ) startdate
12 from (
13 select customer, growth_class, dte, cumu_txns, next_txn, daily_txn
14 , case when growth_class is not null and
15 ( lag(growth_class) over (partition by customer order by dte) is null or
16 lag(growth_class) over (partition by customer order by dte) != growth_class )
17 then dte end growthstartdate
18 from (
19 select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn
20 , case
21 when next_txn >= cumu_txns * 1.20 then 'FAST'
22 when next_txn >= cumu_txns * 1.10 then 'SLOW'
23 end growth_class
24 from (
25 select customer, dte, cumu_txns
26 , lead(cumu_txns) over (
27 partition by customer order by dte
28 ) next_txn
29 from cust_summary
30 ) ) )
31 where growth_class is not null )
32 group by customer, growth_class, startdate
33 having count(*) >= case growth_class when 'FAST' then 1 when 'SLOW' then 2 end
34 order by customer, startdate;
41
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
CUSTOMER GROWTH_CLASS STARTDATE START_TXN END_TXN AVG_DAILY_TXN
------------------- ---------------- --------- ---------- ---------- -------------
Gerald Jones FAST 06-FEB-17 100 130 30
Gerald Jones FAST 08-FEB-17 145 200 55
Gerald Jones SLOW 09-FEB-17 200 315 28.75
John Smith SLOW 02-FEB-17 103 160 14.25
John Smith FAST 07-FEB-17 165 210 45
Sue Brown FAST 07-FEB-17 53 97 22
42
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
easy!
43
¡fácil!
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
44
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
45
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"W T F ?!?"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
analytics are about computation
47
la analítica se trata cálculo
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
users interested in patterns
48
los usuarios están interesados en patrones
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
question
solution
49
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
need a syntax ...
50
necesitamos una sintaxis
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
... to describe patterns
51
para describir patrones
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate, start_txn,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
6 measures
7 classifier() as growth_class
8 , first(dte) as startdate
9 , first(cumu_txns) as start_txn
10 , last(dte) as enddate
11 , next(cumu_txns) as end_txn
12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn
13 one row per match after match skip past last row
14 pattern ( fast+ | slow{2,} )
15 define fast as next(cumu_txns) / cumu_txns >= 1.20
16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and
17 next(slow.cumu_txns) / slow.cumu_txns < 1.20
18 )
19 order by customer, startdate;
52
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
53
CUSTOMER STARTDATE START_TXN END_TXN AVG_DAILY_TXN
------------------- --------- ---------- ---------- -------------
Gerald Jones 06-FEB-17 100 130 30
Gerald Jones 08-FEB-17 145 200 55
Gerald Jones 09-FEB-17 200 315 28.75
John Smith 02-FEB-17 103 160 14.25
John Smith 07-FEB-17 165 210 45
Sue Brown 07-FEB-17 53 97 22
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate, start_txn,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
6 measures
7 classifier() as growth_class
8 , first(dte) as startdate
9 , first(cumu_txns) as start_txn
10 , last(dte) as enddate
11 , next(cumu_txns) as end_txn
12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn
13 one row per match after match skip past last row
14 pattern ( fast+ | slow{2,} )
15 define fast as next(cumu_txns) / cumu_txns >= 1.20
16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and
17 next(slow.cumu_txns) / slow.cumu_txns < 1.20
18 )
19 order by customer, startdate;
54
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
55
CUSTOMER GROWTH_CLASS STARTDATE START_TXN END_TXN AVG_DAILY_TXN
------------------- ---------------- --------- ---------- ---------- -------------
Gerald Jones FAST 06-FEB-17 100 130 30
Gerald Jones FAST 08-FEB-17 145 200 55
Gerald Jones SLOW 09-FEB-17 200 315 28.75
John Smith SLOW 02-FEB-17 103 160 14.25
John Smith FAST 07-FEB-17 165 210 45
Sue Brown FAST 07-FEB-17 53 97 22
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
done !
56
hecho
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"W T F "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"Hello World"
58
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t;
X
----------
1
2
3
5
6
10
11
16
17
9
19
21
30
59
find the odd numbers
X
----------
1
3
5
11
17
9
19
21
encuentra los números impares
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
60
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select x,
2 case when mod(x,2) = 1 then 'Odd' end odd
3 from t;
X ODD
---------- ---
1 Odd
2
3 Odd
5 Odd
6
10
11 Odd
16
17 Odd
9 Odd
19 Odd
21 Odd
30
61
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select x,
2 case when mod(x,2) = 1 then 'Odd' end odd
3 from t
4 where mod(x,2) = 1;
X ODD
---------- ---
1 Odd
3 Odd
5 Odd
11 Odd
17 Odd
9 Odd
19 Odd
21 Odd
62
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"pattern matching talk?"
podemos hablar de patrones?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from
3 ( select x,
4 case when mod(x,2) = 1 then 'Odd' end odd
5 from t
6 )
7 where odd = 1;
X ODD
---------- ---
1 Odd
3 Odd
5 Odd
11 Odd
17 Odd
9 Odd
19 Odd
21 Odd
64
define a variable
pattern = rule using that variable
patrón = regla usando esa variable
definir una variable
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 all rows per match
5 pattern ( odd )
6 define odd as mod(x,2) = 1
7 );
X ODD
---------- ---
1 Odd
3 Odd
5 Odd
11 Odd
17 Odd
9 Odd
19 Odd
21 Odd
65
define a variable
pattern = rule using that variable
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"But.......... WHY?"
"¿Pero por qué?"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t;
X
----------
1
2
3
5
6
10
11
16
17
9
19
21
30
67
find consecutive odd numbers
encontrar consecutivo números impares
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
consecutive = order
68
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t;
X
----------
1
2
3
5
6
10
11
16
17
9
19
21
30
69
find consecutive odd numbers
order by x;
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
encontrar consecutivo números impares
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( odd odd )
7 define odd as mod(x,2) = 1
8 );
X
----------
3
5
17
19
70
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
71
found a match
encontré una coincidencia
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
resume from next row
reanudar desde el próximo registro
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 after match skip to next row
7 pattern ( odd odd )
8 define odd as mod(x,2) = 1
9 );
X
----------
3
5
17
19
21
72
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"Hello World" #2
73
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
my journey
74
mi viaje
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t order by x;
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
75
find contiguous numbers
and show the range
LO HI
---------- ----------
1 3
5 6
9 11
16 17
19 19
21 21
30 30
encontrar números contiguos
y mostrar el rango
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( contig* )
7 define contig as x = prev(x) + 1
8 );
76
regular expression style format
formato de estilo de expresión regular
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"If you have a text parsing problem,
you can use regular expressions…
… now you have two problems"
77
"Si tiene un problema de análisis de texto,
puedes usar expresiones regulares ...
ahora tienes dos problemas
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( contig* )
7 define contig as x = prev(x) + 1
8 );
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
78
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
79
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( contig+ )
7 define contig as x = prev(x) + 1
8 );
X
----------
2
3
6
10
11
17
80
1 2 3
5 6
9 10 11
16 1719
21
30
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( starting_row contig* )
7 define
8 contig as x = prev(x) + 1,
9 starting_row as 1=1
10 );
81
"every row is the potentially the
start of a contiguous sequence…"
cada registro es potencialmente el
comienzo de una secuencia contigua ... "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( starting_row contig* )
7 define
8 contig as x = prev(x) + 1,
9 starting_row as 1=1
10 );
82
"... followed by zero or more
contiguous values"
cada registro es potencialmente el
comienzo de una secuencia contigua ...
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( starting_row contig* )
7 define
8 contig as x = prev(x) + 1,
9 starting_row as 1=1
10 );
83
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by x
5 all rows per match
6 pattern ( starting_row contig* )
7 define contig as x = prev(x) + 1 );
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
84
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
measures
85
what we want to see
lo que queremos ver
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6 all rows per match
7 pattern ( starting_row contig* )
8 define contig as x = prev(x) + 1 );
X LO HI
---------- ---------- ----------
1 1 1
2 1 2
3 1 3
5 5 5
6 5 6
9 9 9
10 9 10
11 9 11
16 16 16
17 16 17
19 19 19
21 21 21
30 30 30
86
first/last row in
the matched pattern
primera / última fila en
el patrón combinado
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"I just want THOSE rows...
Solo quiero esos registros
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"... not ALL of the rows"
no todos los registros
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6 all rows per match
7 pattern ( starting_row contig* )
8 define contig as x = prev(x) + 1 );
LO HI
---------- ----------
1 3
5 6
9 11
16 17
19 19
21 21
30 30
89
6 one row per match
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6
7 pattern ( starting_row contig* )
8 define contig as x = prev(x) + 1 );
LO HI
---------- ----------
1 3
5 6
9 11
16 17
19 19
21 21
30 30
90
one row per match = default
6 one row per match
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
how big is each range ?
91
¿Qué tan grande es cada rango?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6 , count(*) range
7 pattern ( starting_row contig* )
8 define contig as x = prev(x) + 1 );
LO HI RANGE
---------- ---------- ----------
1 3 3
5 6 2
9 11 3
16 17 2
19 19 1
21 21 1
30 30 1
92
Copyright © 2018, Oracle and/or its affiliates. All rights reserved.
"That's not a normal COUNT(*)"
que COUNT(*) no es normal
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
keywords
94
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
95
include the column / expression
incluir la columna / expresión
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
96
value from first row in match
valor de la primera fila del partid
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
97
value from last row in match
valor de la última registros del partido
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
98
value from previous referred row
valor de la registros referida anterior
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
99
value from next referred row
valor de la siguiente registros referida
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
100
count of rows in the match
recuento de registros en el partido
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
101
last encountered row in 'contig'
última registro encontrada en 'contig'
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define contig as x = prev(x) + 1
15 );
X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 2
6 5 6 5 9 2 6 1
11 9 11 10 16 3 11 2
17 16 17 16 19 2 17 1
19 19 19 17 21 1 0
21 21 21 19 30 1 0
30 30 30 21 1 0
102
count of 'contig' rows
conteo de registros 'contig'
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
there's more :-)
109
hay más
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 x x
5 , first(x) lo
6 , last(x) hi
7 , prev(x) prv
8 , next(x) nxt
9 , count(*) range
10 , final last(x) fin
11 , contig.x as contig_x
12 , count(contig.*) contig_count
13 pattern ( starting_row contig* )
14 define
15 contig as x = prev(x) + 1
16 );
X LO HI PRV NXT RANGE FIN CONTIG_X CONTIG_COUNT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------
3 1 3 2 5 3 3 3 2
6 5 6 5 9 2 6 6 1
11 9 11 10 16 3 11 11 2
17 16 17 16 19 2 17 17 1
19 19 19 17 21 1 19 0
21 21 21 19 30 1 21 0
30 30 30 21 1 30 0
110
similar expressions
in DEFINE section
expresiones similares
en la sección DEFINE
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures ... pattern ...
4 DEFINE
5 p1 as x = 1
6 , p2 as first(x) = 1
7 , p3 as last(x) = 1
8 , p4 as prev(x) = 1
9 , p5 as next(x) = 1
10 , p6 as count(*) = 1
11 , p7 as contig.x = 1
12 , p8 as count(contig.*) = 1
13 );
111
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
review
112
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate, start_txn, enddate,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
6 measures
7 classifier() as growth_class
8 , first(dte) as startdate
9 , first(cumu_txns) as start_txn
10 , last(dte) as enddate
11 , next(cumu_txns) as end_txn
12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn
13 one row per match after match skip past last row
14 pattern ( fast+ | slow{3,} )
15 define fast as next(cumu_txns) / cumu_txns >= 1.20
16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and
17 next(slow.cumu_txns) / slow.cumu_txns < 1.20
18 )
19 order by customer, startdate;
113
SQL> select customer, growth_class, startdate, start_txn, enddate,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
6 measures
7 classifier() as growth_class
8 , first(dte) as startdate
9 , first(cumu_txns) as start_txn
10 , last(dte) as enddate
11 , next(cumu_txns) as end_txn
12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn
13 one row per match after match skip past last row
14 pattern ( fast+ | slow{2,} )
15 define fast as next(cumu_txns) / cumu_txns >= 1.20
16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and
17 next(slow.cumu_txns) / slow.cumu_txns < 1.20
18 )
19 order by customer, startdate;
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate, start_txn, enddate,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
...
114
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate, start_txn, enddate,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
...
115
logical subsets
critical
as per analytics
según el análisis
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
patterns
116
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
117
SQL> select customer, growth_class, startdate, start_txn, enddate,
...
14 pattern ( fast+ | slow{3,} )
15 define fast as next(cumu_txns) / cumu_txns >= 1.20
16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and
17 next(slow.cumu_txns) / slow.cumu_txns < 1.20
regular expression syntax
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
*
+
?
{3}
{3,}
{3,6}
{,2}
?
118
0 or more matches
1 or more matches
0 or 1 match
exactly 3 matches
3 or more matches
between 3 and 6 matches
between 0 and 2 matches
reluctance
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
a|b
(a b){3}c
permute a b c
^
$
{- a -}
119
a or b
3 times ( a then b ) then c
abc,acb,bac,bca,cab,cba
first row in pattern
last row in pattern (^ p+ $)
not a
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
reluctance
120
reluctancia
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"How long was someone's job?... i.e
hired, worked for some time, then fired"
121
http://www.kibeha.dk/2015/07/row-pattern-matching-nested-within.html
"¿Cuánto tiempo estuvo el trabajo de alguien? ... es decir
Contratado, trabajado por algún tiempo, luego despedido "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t order by 1;
SEQ COL
---------- ----------
1 Hired
2 Worked
3 Worked
4 Worked
5 Worked
6 Worked
7 Terminated
8 Hired
9 Worked
10 Worked
11 Worked
12 Worked
13 Worked
14 Terminated
15 Hired
16 Worked
17 Worked
18 Worked
19 Worked
20 Worked
21 Terminated
122
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t order by 1;
SEQ COL
---------- ----------
1 Hired
2 Worked
3 Worked
4 Worked
5 Worked
6 Worked
7 Terminated
8 Hired
9 Worked
10 Worked
11 Worked
12 Worked
13 Worked
14 Terminated
15 Hired
16 Worked
17 Worked
18 Worked
19 Worked
20 Worked
21 Terminated
123
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by seq
5 measures
6 first(col) as fcol,
7 col as col,
8 first(seq) p_start,
9 last(seq) p_end,
10 count(*) tot
11 one row per match
12 pattern ( hired worked* fired )
13 define
14 hired as col = 'Hired',
15 fired as col = 'Terminated'
16 );
FCOL COL P_START P_END TOT
---------- ---------- ---------- ---------- ----------
Hired Terminated 1 21 21
124
"always true"
esto siempre es cierto
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 125
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
greediness
126
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t order by 1;
SEQ COL
---------- ----------
1 Hired
2 Worked
3 Worked
4 Worked
5 Worked
6 Worked
7 Terminated
8 Hired
9 Worked
10 Worked
11 Worked
12 Worked
13 Worked
14 Terminated
15 Hired
16 Worked
17 Worked
18 Worked
19 Worked
20 Worked
21 Terminated
127
pattern ( hired worked* fired )
"Cool, I have my 'hired'"
"Awesome, I found 'worked' (ie, anything)"
"Consume as many rows
as I can to see if I can find 'fired'"
"Woo Hoo!"
He encontrado mi 'Hired'
He encontrado mi 'Worked'
"Consume tantas registros
como puedo ver si puedo encontrar 'Fired'
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by seq
5 measures
6 first(col) as fcol,
7 col as col,
8 first(seq) p_start,
9 last(seq) p_end,
10 count(*) tot
11 one row per match
12 pattern ( hired worked*? fired )
13 define
14 hired as col = 'Hired',
15 fired as col = 'Terminated' );
FCOL COL P_START P_END TOT
---------- ---------- ---------- ---------- ----------
Hired Terminated 1 7 7
Hired Terminated 8 14 7
Hired Terminated 15 21 7
128
reluctantly search
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
be careful
129
ten cuidado
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
130
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t order by 1;
SEQ COL
---------- ----------
1 Hired
2 Worked
3 Worked
4 Worked
5 Worked
6 Worked
7 Terminated
8 Worked
9 Worked
10 Worked
11 Worked
12 Worked
13 Worked
14 Worked
15 Worked
16 Worked
17 Worked
18 Worked
19 Worked
20 Worked
21 Worked
131
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by seq
5 measures
6 first(col) as fcol,
7 col as col,
8 first(seq) p_start,
...
ORA-4030: Out of process memory when ...
132
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by seq
5 measures
6 first(col) as fcol,
7 col as col,
8 first(seq) p_start,
9 last(seq) p_end,
10 count(*) tot
11 one row per match
12 pattern ( hired worked* fired )
13 define
14 hired as col = 'Hired',
15 worked as col = 'Worked',
15 fired as col = 'Terminated' );
133
worked+
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t order by 1;
SEQ COL
---------- ----------
1 Hired
2 Worked
3 Worked
4 Worked
5 Worked
6 Worked
7 Terminated
8 Hired
9 Worked
10 Worked
11 Worked
12 Worked
13 Worked
14 Terminated
15 Hired
16 Worked
17 Worked
18 Worked
19 Worked
20 Worked
21 Terminated
134
pattern ( hired worked+ fired )
"Cool, I have my 'hired'"
"Awesome, I found 'worked'"
"worked+ has finished,
now look for fired'"
He encontrado mi 'Hired'
He encontrado mi 'Worked'
worked+ ha terminado,
ahora busca 'fired'
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
“imagination is more
important than knowledge”
- Albert Einstein
135
"La imaginación es más
importante que el conocimiento "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 136
examples
ejemplos
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"count of my subordinates"
137
http://www.kibeha.dk/2015/07/row-pattern-matching-nested-within.html
"cuenta de mis subordinados"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
EMPNO ENAME REPORTS
--------- -------------------- ----------
7839 KING 13
7566 JONES 4
7788 SCOTT 1
7876 ADAMS 0
7902 FORD 1
7369 SMITH 0
7698 BLAKE 5
7499 ALLEN 0
7521 WARD 0
7654 MARTIN 0
7844 TURNER 0
7900 JAMES 0
7782 CLARK 1
7934 MILLER 0
138
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 139
conventional style
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select empno
2 , lpad(' ', (level-1)*2) || ename as ename
3 , ( select count(*)
4 from emp sub
5 start with sub.mgr = emp.empno
6 connect by sub.mgr = prior sub.empno
7 ) reports
8 from emp
9 start with mgr is null
10 connect by mgr = prior empno
11 order siblings by empno;
EMPNO ENAME REPORTS
---------- -------------------- ----------
7839 KING 13
7566 JONES 4
7788 SCOTT 1
7876 ADAMS 0
7902 FORD 1
...
140
select count(*)
from emp sub
start with sub.mgr = emp.empno
connect by sub.mgr = prior sub.empno
select count(*)
from emp sub
start with sub.mgr = emp.empno
connect by sub.mgr = prior sub.empno
select count(*)
from emp sub
start with sub.mgr = emp.empno
connect by sub.mgr = prior sub.empno
select count(*)
from emp sub
start with sub.mgr = emp.empno
connect by sub.mgr = prior sub.empno
select count(*)
from emp sub
start with sub.mgr = emp.empno
connect by sub.mgr = prior sub.empno
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 141
where's the pattern ?
SQL> select ...
2 from cust_summary
3 match_recognize (
4 order by ...
5 pattern ...
...
¿Dónde está el patrón?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
142
ordering sequence
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
143
"starting level"
"nivel inicial"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
144
"starting level"
"next level higher
then starting level?"
"siguiente nivel más alto
entonces nivel inicial?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
145
"starting level"
"next level higher
then starting level?"
"siguiente nivel más alto
entonces nivel inicial?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
146
"starting level"
"next level higher
then starting level?"
"siguiente nivel más alto
entonces nivel inicial?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
147
"Done! How many?"
"¡Listo! ¿Cuántos?"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> with raw_data as (
2 select lvl, empno, ename, rownum as rn
3 from ( select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno )
8 )
...
148
as before
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
...
9 select empno
10 , lpad(' ', (lvl-1)*2) || ename as ename
11 , reports
12 from raw_data
13 match_recognize (
14 order by rn
15 measures
16 starting_level.rn as rn
17 , starting_level.lvl as lvl
18 , starting_level.empno as empno
19 , starting_level.ename as ename
20 , count(higher_level.lvl) as reports
21 one row per match
22 after match skip to next row
23 pattern (starting_level higher_level*)
24 define higher_level as lvl > starting_level.lvl
25 )
26 order by rn;
149
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> with raw_data as (
2 select lvl, empno, ename, rownum as rn
3 from ( select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno )
8 )
9 select empno
10 , lpad(' ', (lvl-1)*2) || ename as ename
11 , reports
12 from raw_data
13 match_recognize (
14 order by rn
15 measures
16 starting_level.rn as rn
17 , starting_level.lvl as lvl
18 , starting_level.empno as empno
19 , starting_level.ename as ename
20 , count(higher_level.lvl) as reports
21 one row per match
22 pattern (starting_level higher_level*)
23 define higher_level as lvl > starting_level.lvl
24 )
25 order by rn;
EMPNO ENAME REPORTS
---------- -------------------- ----------
7839 KING 13
150
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 151
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 152
recall
recordar
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
153
found a match
encontré una coincidencia
X
----------
1
2
3
5
6
9
10
11
16
17
19
21
30
resume from next row
reanudar desde el próximo registro
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
154
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
155
"done!"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
...
9 select empno
10 , lpad(' ', (lvl-1)*2) || ename as ename
11 , reports
12 from raw_data
13 match_recognize (
14 order by rn
15 measures
16 starting_level.rn as rn
17 , starting_level.lvl as lvl
18 , starting_level.empno as empno
19 , starting_level.ename as ename
20 , count(higher_level.lvl) as reports
21 one row per match
22 after match skip to next row
23 pattern (starting_level higher_level*)
24 define higher_level as lvl > starting_level.lvl
25 )
26 order by rn;
156
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select lvl, empno, ename, rownum as rn
2 from (
3 select level as lvl, empno, ename
4 from emp
5 start with mgr is null
6 connect by mgr = prior empno
7 order siblings by empno );
LVL EMPNO ENAME RN
---------- ---------- -------------------- ----------
1 7839 KING 1
2 7566 JONES 2
3 7788 SCOTT 3
4 7876 ADAMS 4
3 7902 FORD 5
4 7369 SMITH 6
2 7698 BLAKE 7
3 7499 ALLEN 8
3 7521 WARD 9
3 7654 MARTIN 10
3 7844 TURNER 11
3 7900 JAMES 12
2 7782 CLARK 13
3 7934 MILLER 14
157
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> with raw_data as (
...
13 match_recognize (
14 order by rn
15 measures
16 starting_level.rn as rn
17 , starting_level.lvl as lvl
18 , starting_level.empno as empno
19 , starting_level.ename as ename
20 , count(higher_level.lvl) as reports
21 one row per match
22 after match skip to next row
23 pattern (starting_level higher_level*)
24 define higher_level as lvl > starting_level.lvl
25 )
26 order by rn;
EMPNO ENAME REPORTS
---------- -------------------- ----------
7839 KING 13
7566 JONES 4
7788 SCOTT 1
7876 ADAMS 0
7902 FORD 1
7369 SMITH 0
7698 BLAKE 5
7499 ALLEN 0
...
158
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 159
the power of a single SQL
un solo SQL tiene mucho poder
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |160
select ename
from emp
where empno = :1
select sum(...)
from emp, dept
group by ...
select min(..)
keep ( dense_rank ) ...
from emp
...
select ...
from emp
match_recognize
measures
define
...
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 161
what if it doesn't work ?
¿Qué pasa si no funciona?
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 162
Requirement "Woo hoo!"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 163
3GL ... we debug
usamos depuración
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
procedure check_auto_no_new_questions
is
l_app_controls_rec ate_application_controls%rowtype;
l_auto_no_new_limit number;
l_new_never_read_cnt number;
begin
apex_debug.message('Checking metadata');
select *
into l_app_controls_rec
from ate_application_controls
where application_code = 'NONEW';
if l_app_controls_rec.enabled = 'Y'
then
apex_debug.message('NONEW');
return;
end if;
apex_debug.message('l_new_never_read_cnt='||l_new_never_read_cnt );
apex_debug.message('l_auto_no_new_limit ='||l_new_never_read_cnt );
if l_new_never_read_cnt >= l_auto_no_new_limit
then
apex_debug.message('Turning off settings');
update ate_application_controls
set enabled = 'Y'
where application_code = 'NONEW';
...
164
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select customer, growth_class, startdate, start_txn, enddate,
2 end_txn, avg_daily_txn
3 from cust_summary
4 match_recognize (
5 partition by customer order by dte
6 measures
7 final last(dte) as termdate
8 , first(dte) as startdate
9 , first(cumu_txns) as start_txn
10 , last(dte) as enddate
11 , next(cumu_txns) as end_txn
12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn
13 one row per match after match skip past last row
14 pattern ( fast+ | slow{3,} )
15 define fast as next(cumu_txns) / cumu_txns >= 1.20
16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and
17 next(slow.cumu_txns) / slow.cumu_txns < 1.20
18 )
19 order by customer, startdate;
165
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 166
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
match_number()
167
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"Hello World"
168
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6 , count(*) range
7 one row per match
8 pattern ( starting_row contig* )
9 define contig as x = prev(x) + 1 );
LO HI RANGE
---------- ---------- ----------
1 3 3
5 6 2
9 11 3
16 17 2
19 19 1
21 21 1
30 30 1
169
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6 , count(*) range
7 , match_number() as mn
8 all rows per match
9 pattern ( starting_row contig* )
10 define contig as x = prev(x) + 1 );
X LO HI RANGE MN
---------- ---------- ---------- ---------- ----------
1 1 1 1 1
2 1 2 2 1
3 1 3 3 1
5 5 5 1 2
6 5 6 2 2
9 9 9 1 3
10 9 10 2 3
11 9 11 3 3
16 16 16 1 4
17 16 17 2 4
19 19 19 1 5
21 21 21 1 6
30 30 30 1 7
170
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
classifier()
171
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures
4 first(x) lo
5 , last(x) hi
6 , count(*) range
7 , match_number() as mn
8 , classifier() as cl
9 all rows per match
10 pattern ( starting_row contig* )
11 define contig as x = prev(x) + 1 );
X LO HI RANGE MN CL
---------- ---------- ---------- ---------- ---------- -------------
1 1 1 1 1 STARTING_ROW
2 1 2 2 1 CONTIG
3 1 3 3 1 CONTIG
5 5 5 1 2 STARTING_ROW
6 5 6 2 2 CONTIG
9 9 9 1 3 STARTING_ROW
10 9 10 2 3 CONTIG
11 9 11 3 3 CONTIG
16 16 16 1 4 STARTING_ROW
17 16 17 2 4 CONTIG
19 19 19 1 5 STARTING_ROW
21 21 21 1 6 STARTING_ROW
30 30 30 1 7 STARTING_ROW
172
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 173
more examples
ejemplos
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
pattern aggregates as measures
174
patrones agregados como medidas
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"W patterns in sales transactions"
175
"Patrones W en transacciones de ventas"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |176
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |177
slope1 = amt < prev(amt)
slope2 = amt > prev(amt)
slope3 = amt < prev(amt)
slope4 = amt < prev(amt)
pattern = ( slope1+ slope2+ slope3+ slope4+ )
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"average AMT in the matched W"
178
"AMT promedio en la W coincidente"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |179
slope1 = amt < prev(amt)
slope2 = amt > prev(amt)
slope3 = amt < prev(amt)
slope4 = amt < prev(amt)
pattern = ( slope1+ slope2+ slope3+ slope4+ )
measures
avg(amt) as w_average
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"average AMT in first downward slide"
180
"AMT promedio en la primera diapositiva descendente"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |181
slope1 = amt < prev(amt)
slope2 = amt > prev(amt)
slope3 = amt < prev(amt)
slope4 = amt < prev(amt)
pattern = ( slope1+ slope2+ slope3+ slope4+ )
measures
avg(slope1.amt) as slide_avg
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
pattern subsets
182
subconjuntos de patrones
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"average AMT in first V of the W"
183
"AMT promedio en la primera V de la W"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |184
slope1 = amt < prev(amt)
slope2 = amt > prev(amt)
slope3 = amt < prev(amt)
slope4 = amt < prev(amt)
pattern = ( slope1+ slope2+ slope3+ slope4+ )
subset s1s2 = ( slope1,slope2)
measures
avg(s1s2.amt) as slide_avg
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
pattern aggregates as predicates
185
agregados de patrones como predicados
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"W patterns in sales transactions,
capped at 7 days"
186
"Patrones de W en transacciones de ventas,
limitado a los 7 días "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |187
slope1 = amt < prev(amt)
slope2 = amt > prev(amt)
slope3 = amt < prev(amt)
slope4 = amt < prev(amt) and
slope4.dte - first(slope1.dte) < 7
Apr 3 Apr 8
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
188
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"Divides a set of weights into 3 equi-sized buckets"
189
https://stewashton.wordpress.com/2014/06/06/bin-fitting-problems-with-sql/
"Divide un conjunto de pesas en 3 cubos de igual tamaño"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t;
KG
----------
1
3
4
6
7
8
11
12
13
14
17
18
19
190
1
3
4
6
7
8
11
12
13
14
17
18
19
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
pattern ( (bin1|bin2|bin3)*
)
define
bin1 as count(bin1.*) = 1
or
sum(bin1.kg) <= least(sum(bin2.kg), sum(bin3.kg)
, bin2 as count(bin2.*) = 1
or
sum(bin2.kg)-bin2.kg <= sum(bin3.kg)
191
I will want 3 bins
(matching my as yet unknown rules)
the bin is empty
- bin1.kg
or my bin has less than either
of the other two bins
... so far
use my bin if ...
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by kg desc
5 measures
6 classifier() bin#,
7 sum(bin1.kg) bin1,
8 sum(bin2.kg) bin2,
9 sum(bin3.kg) bin3
10 all rows per match
11 pattern (
12 (bin1|bin2|bin3)*
13 )
14 define
15 bin1 as count(bin1.*) = 1 or
16 sum(bin1.kg)-bin1.kg <= least(sum(bin2.kg), sum(bin3.kg))
17 , bin2 as count(bin2.*) = 1 or
18 sum(bin2.kg)-bin2.kg <= sum(bin3.kg)
19 );
192
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
KG BIN# BIN1 BIN2 BIN3
---------- ------ ---------- ---------- ----------
19 BIN1 19
18 BIN2 19 18
17 BIN3 19 18 17
14 BIN3 19 18 31
13 BIN2 19 31 31
12 BIN1 31 31 31
11 BIN1 42 31 31
8 BIN2 42 39 31
7 BIN3 42 39 38
6 BIN3 42 39 44
4 BIN2 42 43 44
3 BIN1 45 43 44
1 BIN2 45 44 44
193
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select *
2 from t
3 match_recognize (
4 order by kg desc
5 measures
6 sum(bin1.kg) bin1,
7 sum(bin2.kg) bin2,
8 sum(bin3.kg) bin3
9 pattern (
10 (bin1|bin2|bin3)*
11 )
12 define
13 bin1 as count(bin1.*) = 1 or
14 sum(bin1.kg)-bin1.kg <= least(sum(bin2.kg), sum(bin3.kg))
15 , bin2 as count(bin2.*) = 1 or
16 sum(bin2.kg)-bin2.kg <= sum(bin3.kg)
17 );
BIN1 BIN2 BIN3
---------- ---------- ----------
45 44 44
194
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
aggregates as patterns
195
agregados como patrones
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"If customers reaches their shipping target,
ship the products now. Otherwise ship their products
after 30 days"
196
http://www.kibeha.dk/2015/07/row-pattern-matching-nested-within.html
"Si los clientes alcanzan su objetivo de envío,
envíe los productos ahora. De lo contrario, envíe sus productos
después de 30 días "
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> desc CUST
Name Null? Type
----------------------------- -------- ----------------
CUST_ID NUMBER(38)
CUST_NAME VARCHAR2(30)
MIN_SHIP_VALUE NUMBER(38)
SQL> desc CUST_ORDERS
Name Null? Type
----------------------------- -------- ----------------
CUST_ID NUMBER
ORDER_NO NUMBER
AMT NUMBER(38)
SHIP_DATE DATE
197
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from cust;
CUST_ID CUST_NAME MIN_SHIP_VALUE
---------- ------------------------------ --------------
1 Cust A 350
2 Cust B 750
SQL> select *
2 from cust_orders co
3 order by cust_id, ship_date, order_no;
CUST_ID ORDER_NO AMT SHIP_DATE
---------- ---------- ---------- ---------
1 11 100 31-JAN-17
1 13 10 10-FEB-17
1 12 250 11-FEB-17
1 21 1000 21-FEB-17
1 31 4000 31-MAR-17
2 41 175 31-JAN-17
2 51 100 10-FEB-17
2 42 500 11-FEB-17
2 52 1000 21-FEB-17
2 61 100 31-MAR-17
198
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from cust;
CUST_ID CUST_NAME MIN_SHIP_VALUE
---------- ------------------------------ --------------
1 Cust A 350
2 Cust B 750
SQL> select *
2 from cust_orders co
3 order by cust_id, ship_date, order_no;
CUST_ID ORDER_NO AMT SHIP_DATE
---------- ---------- ---------- ---------
1 11 100 31-JAN-17
1 13 10 10-FEB-17
1 12 250 11-FEB-17
1 21 1000 21-FEB-17
1 31 4000 31-MAR-17
2 41 175 31-JAN-17
2 51 100 10-FEB-17
2 42 500 11-FEB-17
2 52 1000 21-FEB-17
2 61 100 31-MAR-17
199
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from cust;
CUST_ID CUST_NAME MIN_SHIP_VALUE
---------- ------------------------------ --------------
1 Cust A 350
2 Cust B 750
SQL> select *
2 from cust_orders co
3 order by cust_id, ship_date, order_no;
CUST_ID ORDER_NO AMT SHIP_DATE
---------- ---------- ---------- ---------
1 11 100 31-JAN-17
1 13 10 10-FEB-17
1 12 250 11-FEB-17
1 21 1000 21-FEB-17
1 31 4000 31-MAR-17
2 41 175 31-JAN-17
2 51 100 10-FEB-17
2 42 500 11-FEB-17
2 52 1000 21-FEB-17
2 61 100 31-MAR-17
200
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
pattern
201
"any number under the shipping limit"
UNDER_LIMIT*
"then hit/exceed the shipping limit"
OVER_LIMIT
"some might never hit the shipping limit"
{0,1}
"cualquier número bajo el límite de envío"
luego exceden el límite de envío
"algunos pueden nunca alcanzar el límite de envío"
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
definitions
202
UNDER_LIMIT
OVER_LIMIT
"rolling" sum(amt) < cust.min_ship_limit
"rolling" sum(amt) >= cust.min_ship_limit
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
recall
203
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from t
2 match_recognize ( order by x
3 measures ... pattern ...
4 DEFINE
5 p1 as x = 1
6 , p2 as first(x) = 1
7 , p3 as last(x) = 1
8 , p4 as prev(x) = 1
9 , p5 as next(x) = 1
10 , p6 as count(*) = 1
11 , p7 as final last(x) = 1
12 , p8 as contig.x = 1
13 , p9 as count(contig.*) = 1
14 );
204
as per ALL ROWS PER MATCH
- this row
- first row of match pattern
- this row
- previous row from this row
- next row from this row
- count from first to this row
- ILLEGAL
- this 'contig' row
- count from first to this contig row
contar desde el primero hasta esta fila
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from (
2 select co.*, c.min_ship_value
3 from cust c, cust_orders co
4 where c.cust_id = co.cust_id
5 )
6 match_recognize (
7 partition by cust_id
8 order by ship_date, order_no
9 measures
10 match_number() as mno,
11 classifier() as cls,
12 sum(amt) as tot
13 all rows per match
14 pattern ( under_limit* over_limit{0,1} )
15 define
16 under_limit as sum(amt) < min_ship_value,
17 over_limit as sum(amt) >= min_ship_value );
CUST_ID SHIP_DATE ORDER_NO MNO CLS TOT AMT MIN_SHIP_VALUE
---------- --------- ---------- ----- --------------- ---------- ---------- --------------
1 31-JAN-17 11 1 UNDER_LIMIT 100 100 350
1 10-FEB-17 13 1 UNDER_LIMIT 110 10 350
1 11-FEB-17 12 1 OVER_LIMIT 360 250 350
1 21-FEB-17 21 2 OVER_LIMIT 1000 1000 350
1 31-MAR-17 31 3 OVER_LIMIT 4000 4000 350
2 31-JAN-17 41 1 UNDER_LIMIT 175 175 750
2 10-FEB-17 51 1 UNDER_LIMIT 275 100 750
2 11-FEB-17 42 1 OVER_LIMIT 775 500 750
2 21-FEB-17 52 2 OVER_LIMIT 1000 1000 750
2 31-MAR-17 61 3 UNDER_LIMIT 100 100 750
205
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
"If customers hit their minimum shipping target,
ship that batch now. Otherwise ship their products
after 30 days"
206
De lo contrario, envíe sus productos
después de 30 días
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
SQL> select * from (
2 select co.*, c.min_ship_value
3 from cust c, cust_orders co
4 where c.cust_id = co.cust_id
5 )
6 match_recognize (
7 partition by cust_id
8 order by ship_date, order_no
9 measures
10 match_number() as mno,
11 classifier() as cls,
12 sum(amt) as tot,
13 nvl(final last(over_limit.ship_date), last(ship_date)+30) last_ship_date
14 all rows per match
15 pattern ( under_limit* over_limit{0,1} )
16 define
17 under_limit as sum(amt) < min_ship_value,
18 over_limit as sum(amt) >= min_ship_value );
207
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 208
wrap up
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 209
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 210
be patient
se paciente
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 211
match_number()
classifier()
ALL ROWS PER MATCH
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |
Thank you!
youtube bit.ly/youtube-connor
blog bit.ly/blog-connor
twitter bit.ly/twitter-connor
Gracias!

More Related Content

What's hot

What's hot (20)

Latin America Tour 2019 - slow data and sql processing
Latin America Tour 2019  - slow data and sql processingLatin America Tour 2019  - slow data and sql processing
Latin America Tour 2019 - slow data and sql processing
 
Flashback features in Oracle - UKOUG 2017
Flashback features in Oracle - UKOUG 2017Flashback features in Oracle - UKOUG 2017
Flashback features in Oracle - UKOUG 2017
 
APEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQLAPEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQL
 
Cool SQL Features
Cool SQL FeaturesCool SQL Features
Cool SQL Features
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
 
KScope19 - SQL Features
KScope19 - SQL FeaturesKScope19 - SQL Features
KScope19 - SQL Features
 
Latin America Tour 2019 - 18c and 19c featues
Latin America Tour 2019   - 18c and 19c featuesLatin America Tour 2019   - 18c and 19c featues
Latin America Tour 2019 - 18c and 19c featues
 
ANSI vs Oracle language
ANSI vs Oracle languageANSI vs Oracle language
ANSI vs Oracle language
 
Perth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL TechniquesPerth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL Techniques
 
UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL features
 
Sangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestSangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolest
 
Sangam 19 - Analytic SQL
Sangam 19 - Analytic SQLSangam 19 - Analytic SQL
Sangam 19 - Analytic SQL
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on Autonomous
 
UKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tipsUKOUG - 25 years of hints and tips
UKOUG - 25 years of hints and tips
 
OOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAs
 
Flashback ITOUG
Flashback ITOUGFlashback ITOUG
Flashback ITOUG
 
Wellington APAC Groundbreakers tour - Upgrading to the 12c Optimizer
Wellington APAC Groundbreakers tour - Upgrading to the 12c OptimizerWellington APAC Groundbreakers tour - Upgrading to the 12c Optimizer
Wellington APAC Groundbreakers tour - Upgrading to the 12c Optimizer
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL features
 
SQL techniques for faster applications
SQL techniques for faster applicationsSQL techniques for faster applications
SQL techniques for faster applications
 
Oracle Database 12c Application Development
Oracle Database 12c Application DevelopmentOracle Database 12c Application Development
Oracle Database 12c Application Development
 

Similar to Latin America Tour 2019 - pattern matching

Similar to Latin America Tour 2019 - pattern matching (20)

Wellington APAC Groundbreakers tour - SQL Pattern Matching
Wellington APAC Groundbreakers tour - SQL Pattern MatchingWellington APAC Groundbreakers tour - SQL Pattern Matching
Wellington APAC Groundbreakers tour - SQL Pattern Matching
 
18c and 19c features for DBAs
18c and 19c features for DBAs18c and 19c features for DBAs
18c and 19c features for DBAs
 
Melbourne Groundbreakers Tour - Upgrading without risk
Melbourne Groundbreakers Tour - Upgrading without riskMelbourne Groundbreakers Tour - Upgrading without risk
Melbourne Groundbreakers Tour - Upgrading without risk
 
Sangam 18 - The New Optimizer in Oracle 12c
Sangam 18 - The New Optimizer in Oracle 12cSangam 18 - The New Optimizer in Oracle 12c
Sangam 18 - The New Optimizer in Oracle 12c
 
OpenWorld 2018 - SQL Tuning in 20 mins
OpenWorld 2018 - SQL Tuning in 20 minsOpenWorld 2018 - SQL Tuning in 20 mins
OpenWorld 2018 - SQL Tuning in 20 mins
 
ITOUG 2019 - 18c, 19c features
ITOUG 2019 - 18c, 19c featuresITOUG 2019 - 18c, 19c features
ITOUG 2019 - 18c, 19c features
 
Top 10 SQL Performance tips & tricks for Java Developers
Top 10 SQL Performance tips & tricks for Java DevelopersTop 10 SQL Performance tips & tricks for Java Developers
Top 10 SQL Performance tips & tricks for Java Developers
 
Hyderabad Mar 2019 - Database 18c / 19c
Hyderabad Mar 2019 - Database 18c / 19cHyderabad Mar 2019 - Database 18c / 19c
Hyderabad Mar 2019 - Database 18c / 19c
 
Analytic functions in Oracle SQL - BIWA 2017
Analytic functions in Oracle SQL - BIWA 2017Analytic functions in Oracle SQL - BIWA 2017
Analytic functions in Oracle SQL - BIWA 2017
 
Perth APAC Groundbreakers tour - 18c features
Perth APAC Groundbreakers tour - 18c featuresPerth APAC Groundbreakers tour - 18c features
Perth APAC Groundbreakers tour - 18c features
 
Melbourne Groundbreakers Tour - Hints and Tips
Melbourne Groundbreakers Tour - Hints and TipsMelbourne Groundbreakers Tour - Hints and Tips
Melbourne Groundbreakers Tour - Hints and Tips
 
OG Yatra - Flashback, not just for developers
OG Yatra - Flashback, not just for developersOG Yatra - Flashback, not just for developers
OG Yatra - Flashback, not just for developers
 
OG Yatra - upgrading to the new 12c+ optimizer
OG Yatra - upgrading to the new 12c+ optimizerOG Yatra - upgrading to the new 12c+ optimizer
OG Yatra - upgrading to the new 12c+ optimizer
 
Redo logfile addition in oracle rac 12c
Redo logfile addition in oracle rac 12cRedo logfile addition in oracle rac 12c
Redo logfile addition in oracle rac 12c
 
Five more things about Oracle SQL and PLSQL
Five more things about Oracle SQL and PLSQLFive more things about Oracle SQL and PLSQL
Five more things about Oracle SQL and PLSQL
 
A close encounter_with_real_world_and_odd_perf_issues
A close encounter_with_real_world_and_odd_perf_issuesA close encounter_with_real_world_and_odd_perf_issues
A close encounter_with_real_world_and_odd_perf_issues
 
Flashback features in Oracle - UKOUG 2017
Flashback features in Oracle - UKOUG 2017Flashback features in Oracle - UKOUG 2017
Flashback features in Oracle - UKOUG 2017
 
ILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for DevelopersILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for Developers
 
ILOUG 2019 - Flashback, the forgotten feature
ILOUG 2019 - Flashback, the forgotten featureILOUG 2019 - Flashback, the forgotten feature
ILOUG 2019 - Flashback, the forgotten feature
 
Advanced SQL - Quebec 2014
Advanced SQL - Quebec 2014Advanced SQL - Quebec 2014
Advanced SQL - Quebec 2014
 

More from Connor McDonald

More from Connor McDonald (8)

APEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomousAPEX tour 2019 - successful development with autonomous
APEX tour 2019 - successful development with autonomous
 
APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne
 
OOW19 - Read consistency
OOW19 - Read consistencyOOW19 - Read consistency
OOW19 - Read consistency
 
OOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsOOW19 - Slower and less secure applications
OOW19 - Slower and less secure applications
 
OOW19 - Killing database sessions
OOW19 - Killing database sessionsOOW19 - Killing database sessions
OOW19 - Killing database sessions
 
OG Yatra - 25 years of hints and tips
OG Yatra - 25 years of hints and tipsOG Yatra - 25 years of hints and tips
OG Yatra - 25 years of hints and tips
 
Kscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processingKscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processing
 
APEX Connect 2019 - successful application development
APEX Connect 2019 - successful application developmentAPEX Connect 2019 - successful application development
APEX Connect 2019 - successful application development
 

Recently uploaded

Recently uploaded (20)

Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 

Latin America Tour 2019 - pattern matching

  • 1. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | bienvenido
  • 2. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | Lo siento, no hablo español :-(
  • 3. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. |Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | But I will do my best to help Pero haré todo lo posible para ayudar
  • 4. Pattern Matching Connor McDonald Database Advocate La coincidencia de patrones
  • 5. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Connor McDonald
  • 6. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 6
  • 7. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 7
  • 8. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | Me youtube bit.ly/youtube-connor blog bit.ly/blog-connor twitter bit.ly/twitter-connor 400+ posts mainly on database & development 250 technical videos, new uploads every week Más de 400 publicaciones principalmente en bases de datos y desarrollo 250 videos técnicos, nuevas cargas cada semana
  • 9. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. etc... facebook bit.ly/facebook-connor linkedin bit.ly/linkedin-connor instagram bit.ly/instagram-connor slideshare bit.ly/slideshare-connor
  • 10. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 10https://asktom.oracle.com
  • 11. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. https://asktom.oracle.com/officehours
  • 12. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 12 SQL> lots and lots and lots of code :-) SQL> mucho mucho mucho código
  • 13. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | classical problem 13 problema clásico
  • 14. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select deptno, ename 2 from emp 3 order by 1,2; DEPTNO ENAME ---------- ---------- 10 CLARK 10 KING 10 MILLER 20 ADAMS 20 FORD 20 JONES 20 SCOTT 20 SMITH 30 ALLEN 30 BLAKE 30 JAMES 30 MARTIN 30 TURNER 30 WARD 14
  • 15. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | DEPTNO MEMBERS ---------- ------------------------------------- 10 CLARK,KING,MILLER 20 SMITH,JONES,SCOTT,ADAMS,FORD 30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES 15
  • 16. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | how we used to do it 16 como solíamos hacerlo
  • 17. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select deptno , rtrim(ename,',') enames 2 from ( select deptno,ename,rn 3 from emp 4 model 5 partition by (deptno) 6 dimension by ( 7 row_number() over 8 (partition by deptno order by ename) rn 9 ) 10 measures (cast(ename as varchar2(40)) ename) 11 rules 12 ( ename[any] 13 order by rn desc = ename[cv()]||','||ename[cv()+1]) 14 ) 15 where rn = 1 16 order by deptno; DEPTNO ENAMES ---------- ---------------------------------------- 10 CLARK,KING,MILLER 20 ADAMS,FORD,JONES,SCOTT,SMITH 30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD 17
  • 18. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select deptno, 2 substr(max(sys_connect_by_path(ename, ',')), 2) members 3 from (select deptno, ename, 4 row_number () 5 over (partition by deptno order by empno) rn 6 from emp) 7 start with rn = 1 8 connect by prior rn = rn - 1 9 and prior deptno = deptno 10 group by deptno 11 / DEPTNO MEMBERS ---------- --------------------------------------------------------- 30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES 20 SMITH,JONES,SCOTT,ADAMS,FORD 10 CLARK,KING,MILLER 18
  • 19. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select deptno, 2 xmltransform 3 ( sys_xmlagg 4 ( sys_xmlgen(ename) 5 ), 6 xmltype 7 ( 8 '<?xml version="1.0"?><xsl:stylesheet version="1.0" 9 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 10 <xsl:template match="/"> 11 <xsl:for-each select="/ROWSET/ENAME"> 12 <xsl:value-of select="text()"/>,</xsl:for-each> 13 </xsl:template> 14 </xsl:stylesheet>' 15 ) 16 ).getstringval() members 17 from emp 18 group by deptno; DEPTNO MEMBERS ---------- -------------------------------------------------------- 10 CLARK,MILLER,KING, 20 SMITH,FORD,ADAMS,SCOTT,JONES, 30 ALLEN,JAMES,TURNER,BLAKE,MARTIN,WARD, 19
  • 20. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> create or replace type string_agg_type as object 2 ( 3 total varchar2(4000), 4 5 static function 6 ODCIAggregateInitialize(sctx IN OUT string_agg_type ) 7 return number, 8 9 member function 10 ODCIAggregateIterate(self IN OUT string_agg_type , 11 value IN varchar2 ) 12 return number, 13 14 member function 15 ODCIAggregateTerminate(self IN string_agg_type, 16 returnValue OUT varchar2, 17 flags IN number) 18 return number, 19 20 member function 21 ODCIAggregateMerge(self IN OUT string_agg_type, 22 ctx2 IN string_agg_type) 23 return number 24 ); 25 / 20
  • 21. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 11g 21
  • 22. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select deptno, 2 listagg( ename, ',') 3 within group (order by empno) members 4 from emp 5 group by deptno; DEPTNO MEMBERS ---------- ----------------------------------------- 10 CLARK,KING,MILLER 20 SMITH,JONES,SCOTT,ADAMS,FORD 30 ALLEN,WARD,MARTIN,BLAKE,TURNER,JAMES 22
  • 23. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | question solution 23 pregunta solución
  • 24. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select deptno, 2 listagg( ename, ',') 3 within group (order by empno) members 4 from emp 5 group by deptno; 24
  • 25. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | still challenges 25 todavía hay desafíos
  • 26. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | example 26 ejemplo
  • 27. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 27
  • 28. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 28
  • 29. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "I want to reward active customers… If their transaction volume grows by 20% in a day, or grows by 10% for 2 consecutive days, then show me their details" 29 "Quiero recompensar a los clientes activos ... Si su volumen de transacciones crece un 20% en un día, o crece un 10% durante 2 días consecutivos, entonces muéstrame sus detalles "
  • 30. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from cust_summary 2 order by 1,2; CUSTOMER DTE TXN_CNT ------------------------------ --------- ---------- Gerald Jones 06-FEB-17 100 Gerald Jones 07-FEB-17 130 Gerald Jones 08-FEB-17 145 Gerald Jones 09-FEB-17 200 Gerald Jones 10-FEB-17 225 Gerald Jones 11-FEB-17 255 Gerald Jones 12-FEB-17 285 Gerald Jones 13-FEB-17 315 John Smith 01-FEB-17 100 John Smith 02-FEB-17 103 John Smith 03-FEB-17 116 John Smith 04-FEB-17 129 John Smith 05-FEB-17 142 Sue Brown 06-FEB-17 50 Sue Brown 07-FEB-17 53 Sue Brown 08-FEB-17 72 ... 30 20% in a day 10% each day over 2 days
  • 31. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 31
  • 32. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | analytics 32 analítica
  • 33. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select row_number() OVER ( order by sal ) 2 from emp 3 ... 33 https://bit.ly/analytic_sql
  • 34. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "I want to reward active customers… If their transaction volume grows by 20% in a day, or grows by 10% for 2 consecutive days, then show me the details" 34 En un día
  • 35. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn 2 from ( 3 select customer, dte, cumu_txns 4 , lead(cumu_txns) over ( 5 partition by customer order by dte 6 ) next_txn 7 from cust_summary 8 ); CUSTOMER DTE CUMU_TXNS NEXT_TXN DAILY_TXN ------------------------------ --------- ---------- ---------- ---------- Gerald Jones 06-FEB-17 100 130 30 Gerald Jones 07-FEB-17 130 145 15 Gerald Jones 08-FEB-17 145 200 55 Gerald Jones 09-FEB-17 200 225 25 Gerald Jones 10-FEB-17 225 255 30 35
  • 36. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "I want to reward active customers… If their transaction volume grows by 20% in a day, or grows by 10% for 2 consecutive days, then show me the details" 36 crece un 20% en un día, o crece en un 10%
  • 37. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn 2 , case 3 when next_txn >= cumu_txns * 1.20 then 'FAST' 4 when next_txn >= cumu_txns * 1.10 then 'SLOW' 5 end growth_class 6 from ( 7 select customer, dte, cumu_txns 8 , lead(cumu_txns) over ( 9 partition by customer order by dte 10 ) next_txn 11 from cust_summary 12 ); CUSTOMER DTE CUMU_TXNS NEXT_TXN DAILY_TXN GROWTH_CLASS ------------------------------ --------- ---------- ---------- ---------- ------------ Gerald Jones 06-FEB-17 100 130 30 FAST Gerald Jones 07-FEB-17 130 145 15 SLOW Gerald Jones 08-FEB-17 145 200 55 FAST Gerald Jones 09-FEB-17 200 225 25 SLOW Gerald Jones 10-FEB-17 225 255 30 SLOW Gerald Jones 11-FEB-17 255 285 30 SLOW Gerald Jones 12-FEB-17 285 315 30 SLOW 37
  • 38. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "I want to reward active customers… If their transaction volume grows by 20% in a day, or grows by 10% for 2 consecutive days, then show me the details" 38 2 días consecutivos
  • 39. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, dte, cumu_txns, next_txn, daily_txn 2 , case 3 when growth_class is not null and 4 ( lag(growth_class) over ( 5 partition by customer order by dte 6 ) is null 7 or 8 lag(growth_class) over ( 9 partition by customer order by dte 10 ) != growth_class 11 ) 12 then dte 13 end growthstartdate 14 from ( 15 select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn 16 , case 17 when next_txn >= cumu_txns * 1.20 then 'FAST' 18 when next_txn >= cumu_txns * 1.10 then 'SLOW' 19 end growth_class 20 from ( 21 select customer, dte, cumu_txns 22 , lead(cumu_txns) over ( 23 partition by customer order by dte 24 ) next_txn 25 from cust_summary 26 ) ) 39
  • 40. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, dte, cumu_txns, next_txn, daily_txn 2 , last_value(growthstartdate ignore nulls) over ( 3 partition by customer, growth_class order by dte 4 rows between unbounded preceding and current row 5 ) startdate 6 from ( 7 select customer, growth_class, dte, cumu_txns, next_txn, daily_txn 8 , case 9 when growth_class is not null and 10 ( lag(growth_class) over ( 11 partition by customer order by dte ) is null or 12 lag(growth_class) over ( 13 partition by customer order by dte 14 ) != growth_class ) 15 then dte 16 end growthstartdate 17 from ( 18 select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn 19 , case when next_txn >= cumu_txns * 1.20 then 'FAST' 20 when next_txn >= cumu_txns * 1.10 then 'SLOW' 21 end growth_class 22 from ( 23 select customer, dte, cumu_txns 24 , lead(cumu_txns) over (partition by customer order by dte 25 ) next_txn 26 from cust_summary 27 ) ) ) 28 where growth_class is not null 40
  • 41. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate 2 , min(cumu_txns) keep (dense_rank first order by dte) start_txn 3 , max(dte) enddate 4 , max(next_txn) keep (dense_rank last order by dte) end_txn 5 , avg(daily_txn) avg_daily_txn 6 from ( 7 select customer, growth_class, dte, cumu_txns, next_txn, daily_txn 8 , last_value(growthstartdate ignore nulls) over ( 9 partition by customer, growth_class order by dte 10 rows between unbounded preceding and current row 11 ) startdate 12 from ( 13 select customer, growth_class, dte, cumu_txns, next_txn, daily_txn 14 , case when growth_class is not null and 15 ( lag(growth_class) over (partition by customer order by dte) is null or 16 lag(growth_class) over (partition by customer order by dte) != growth_class ) 17 then dte end growthstartdate 18 from ( 19 select customer, dte, cumu_txns, next_txn, next_txn - cumu_txns daily_txn 20 , case 21 when next_txn >= cumu_txns * 1.20 then 'FAST' 22 when next_txn >= cumu_txns * 1.10 then 'SLOW' 23 end growth_class 24 from ( 25 select customer, dte, cumu_txns 26 , lead(cumu_txns) over ( 27 partition by customer order by dte 28 ) next_txn 29 from cust_summary 30 ) ) ) 31 where growth_class is not null ) 32 group by customer, growth_class, startdate 33 having count(*) >= case growth_class when 'FAST' then 1 when 'SLOW' then 2 end 34 order by customer, startdate; 41
  • 42. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | CUSTOMER GROWTH_CLASS STARTDATE START_TXN END_TXN AVG_DAILY_TXN ------------------- ---------------- --------- ---------- ---------- ------------- Gerald Jones FAST 06-FEB-17 100 130 30 Gerald Jones FAST 08-FEB-17 145 200 55 Gerald Jones SLOW 09-FEB-17 200 315 28.75 John Smith SLOW 02-FEB-17 103 160 14.25 John Smith FAST 07-FEB-17 165 210 45 Sue Brown FAST 07-FEB-17 53 97 22 42
  • 43. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | easy! 43 ¡fácil!
  • 44. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 44
  • 45. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 45
  • 46. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "W T F ?!?"
  • 47. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | analytics are about computation 47 la analítica se trata cálculo
  • 48. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | users interested in patterns 48 los usuarios están interesados en patrones
  • 49. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | question solution 49
  • 50. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | need a syntax ... 50 necesitamos una sintaxis
  • 51. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ... to describe patterns 51 para describir patrones
  • 52. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate, start_txn, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte 6 measures 7 classifier() as growth_class 8 , first(dte) as startdate 9 , first(cumu_txns) as start_txn 10 , last(dte) as enddate 11 , next(cumu_txns) as end_txn 12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn 13 one row per match after match skip past last row 14 pattern ( fast+ | slow{2,} ) 15 define fast as next(cumu_txns) / cumu_txns >= 1.20 16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and 17 next(slow.cumu_txns) / slow.cumu_txns < 1.20 18 ) 19 order by customer, startdate; 52
  • 53. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 53 CUSTOMER STARTDATE START_TXN END_TXN AVG_DAILY_TXN ------------------- --------- ---------- ---------- ------------- Gerald Jones 06-FEB-17 100 130 30 Gerald Jones 08-FEB-17 145 200 55 Gerald Jones 09-FEB-17 200 315 28.75 John Smith 02-FEB-17 103 160 14.25 John Smith 07-FEB-17 165 210 45 Sue Brown 07-FEB-17 53 97 22
  • 54. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate, start_txn, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte 6 measures 7 classifier() as growth_class 8 , first(dte) as startdate 9 , first(cumu_txns) as start_txn 10 , last(dte) as enddate 11 , next(cumu_txns) as end_txn 12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn 13 one row per match after match skip past last row 14 pattern ( fast+ | slow{2,} ) 15 define fast as next(cumu_txns) / cumu_txns >= 1.20 16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and 17 next(slow.cumu_txns) / slow.cumu_txns < 1.20 18 ) 19 order by customer, startdate; 54
  • 55. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 55 CUSTOMER GROWTH_CLASS STARTDATE START_TXN END_TXN AVG_DAILY_TXN ------------------- ---------------- --------- ---------- ---------- ------------- Gerald Jones FAST 06-FEB-17 100 130 30 Gerald Jones FAST 08-FEB-17 145 200 55 Gerald Jones SLOW 09-FEB-17 200 315 28.75 John Smith SLOW 02-FEB-17 103 160 14.25 John Smith FAST 07-FEB-17 165 210 45 Sue Brown FAST 07-FEB-17 53 97 22
  • 56. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | done ! 56 hecho
  • 57. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "W T F "
  • 58. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "Hello World" 58
  • 59. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t; X ---------- 1 2 3 5 6 10 11 16 17 9 19 21 30 59 find the odd numbers X ---------- 1 3 5 11 17 9 19 21 encuentra los números impares
  • 60. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 60
  • 61. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select x, 2 case when mod(x,2) = 1 then 'Odd' end odd 3 from t; X ODD ---------- --- 1 Odd 2 3 Odd 5 Odd 6 10 11 Odd 16 17 Odd 9 Odd 19 Odd 21 Odd 30 61
  • 62. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select x, 2 case when mod(x,2) = 1 then 'Odd' end odd 3 from t 4 where mod(x,2) = 1; X ODD ---------- --- 1 Odd 3 Odd 5 Odd 11 Odd 17 Odd 9 Odd 19 Odd 21 Odd 62
  • 63. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "pattern matching talk?" podemos hablar de patrones?
  • 64. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from 3 ( select x, 4 case when mod(x,2) = 1 then 'Odd' end odd 5 from t 6 ) 7 where odd = 1; X ODD ---------- --- 1 Odd 3 Odd 5 Odd 11 Odd 17 Odd 9 Odd 19 Odd 21 Odd 64 define a variable pattern = rule using that variable patrón = regla usando esa variable definir una variable
  • 65. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 all rows per match 5 pattern ( odd ) 6 define odd as mod(x,2) = 1 7 ); X ODD ---------- --- 1 Odd 3 Odd 5 Odd 11 Odd 17 Odd 9 Odd 19 Odd 21 Odd 65 define a variable pattern = rule using that variable
  • 66. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "But.......... WHY?" "¿Pero por qué?"
  • 67. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t; X ---------- 1 2 3 5 6 10 11 16 17 9 19 21 30 67 find consecutive odd numbers encontrar consecutivo números impares
  • 68. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | consecutive = order 68
  • 69. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t; X ---------- 1 2 3 5 6 10 11 16 17 9 19 21 30 69 find consecutive odd numbers order by x; X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 encontrar consecutivo números impares
  • 70. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( odd odd ) 7 define odd as mod(x,2) = 1 8 ); X ---------- 3 5 17 19 70 X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 ?
  • 71. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 71 found a match encontré una coincidencia X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 resume from next row reanudar desde el próximo registro
  • 72. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 after match skip to next row 7 pattern ( odd odd ) 8 define odd as mod(x,2) = 1 9 ); X ---------- 3 5 17 19 21 72 X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30
  • 73. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "Hello World" #2 73
  • 74. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | my journey 74 mi viaje
  • 75. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t order by x; X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 75 find contiguous numbers and show the range LO HI ---------- ---------- 1 3 5 6 9 11 16 17 19 19 21 21 30 30 encontrar números contiguos y mostrar el rango
  • 76. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( contig* ) 7 define contig as x = prev(x) + 1 8 ); 76 regular expression style format formato de estilo de expresión regular
  • 77. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "If you have a text parsing problem, you can use regular expressions… … now you have two problems" 77 "Si tiene un problema de análisis de texto, puedes usar expresiones regulares ... ahora tienes dos problemas
  • 78. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( contig* ) 7 define contig as x = prev(x) + 1 8 ); X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 78
  • 79. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 79
  • 80. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( contig+ ) 7 define contig as x = prev(x) + 1 8 ); X ---------- 2 3 6 10 11 17 80 1 2 3 5 6 9 10 11 16 1719 21 30
  • 81. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( starting_row contig* ) 7 define 8 contig as x = prev(x) + 1, 9 starting_row as 1=1 10 ); 81 "every row is the potentially the start of a contiguous sequence…" cada registro es potencialmente el comienzo de una secuencia contigua ... "
  • 82. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( starting_row contig* ) 7 define 8 contig as x = prev(x) + 1, 9 starting_row as 1=1 10 ); 82 "... followed by zero or more contiguous values" cada registro es potencialmente el comienzo de una secuencia contigua ...
  • 83. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( starting_row contig* ) 7 define 8 contig as x = prev(x) + 1, 9 starting_row as 1=1 10 ); 83
  • 84. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by x 5 all rows per match 6 pattern ( starting_row contig* ) 7 define contig as x = prev(x) + 1 ); X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 84
  • 85. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | measures 85 what we want to see lo que queremos ver
  • 86. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 all rows per match 7 pattern ( starting_row contig* ) 8 define contig as x = prev(x) + 1 ); X LO HI ---------- ---------- ---------- 1 1 1 2 1 2 3 1 3 5 5 5 6 5 6 9 9 9 10 9 10 11 9 11 16 16 16 17 16 17 19 19 19 21 21 21 30 30 30 86 first/last row in the matched pattern primera / última fila en el patrón combinado
  • 87. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "I just want THOSE rows... Solo quiero esos registros
  • 88. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "... not ALL of the rows" no todos los registros
  • 89. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 all rows per match 7 pattern ( starting_row contig* ) 8 define contig as x = prev(x) + 1 ); LO HI ---------- ---------- 1 3 5 6 9 11 16 17 19 19 21 21 30 30 89 6 one row per match
  • 90. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 7 pattern ( starting_row contig* ) 8 define contig as x = prev(x) + 1 ); LO HI ---------- ---------- 1 3 5 6 9 11 16 17 19 19 21 21 30 30 90 one row per match = default 6 one row per match
  • 91. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | how big is each range ? 91 ¿Qué tan grande es cada rango?
  • 92. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 , count(*) range 7 pattern ( starting_row contig* ) 8 define contig as x = prev(x) + 1 ); LO HI RANGE ---------- ---------- ---------- 1 3 3 5 6 2 9 11 3 16 17 2 19 19 1 21 21 1 30 30 1 92
  • 93. Copyright © 2018, Oracle and/or its affiliates. All rights reserved. "That's not a normal COUNT(*)" que COUNT(*) no es normal
  • 94. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | keywords 94
  • 95. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 95 include the column / expression incluir la columna / expresión
  • 96. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 96 value from first row in match valor de la primera fila del partid
  • 97. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 97 value from last row in match valor de la última registros del partido
  • 98. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 98 value from previous referred row valor de la registros referida anterior
  • 99. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 99 value from next referred row valor de la siguiente registros referida
  • 100. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 100 count of rows in the match recuento de registros en el partido
  • 101. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 101 last encountered row in 'contig' última registro encontrada en 'contig'
  • 102. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define contig as x = prev(x) + 1 15 ); X LO HI PRV NXT RANGE CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 2 6 5 6 5 9 2 6 1 11 9 11 10 16 3 11 2 17 16 17 16 19 2 17 1 19 19 19 17 21 1 0 21 21 21 19 30 1 0 30 30 30 21 1 0 102 count of 'contig' rows conteo de registros 'contig'
  • 103. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | there's more :-) 109 hay más
  • 104. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 x x 5 , first(x) lo 6 , last(x) hi 7 , prev(x) prv 8 , next(x) nxt 9 , count(*) range 10 , final last(x) fin 11 , contig.x as contig_x 12 , count(contig.*) contig_count 13 pattern ( starting_row contig* ) 14 define 15 contig as x = prev(x) + 1 16 ); X LO HI PRV NXT RANGE FIN CONTIG_X CONTIG_COUNT ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------ 3 1 3 2 5 3 3 3 2 6 5 6 5 9 2 6 6 1 11 9 11 10 16 3 11 11 2 17 16 17 16 19 2 17 17 1 19 19 19 17 21 1 19 0 21 21 21 19 30 1 21 0 30 30 30 21 1 30 0 110 similar expressions in DEFINE section expresiones similares en la sección DEFINE
  • 105. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures ... pattern ... 4 DEFINE 5 p1 as x = 1 6 , p2 as first(x) = 1 7 , p3 as last(x) = 1 8 , p4 as prev(x) = 1 9 , p5 as next(x) = 1 10 , p6 as count(*) = 1 11 , p7 as contig.x = 1 12 , p8 as count(contig.*) = 1 13 ); 111
  • 106. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | review 112
  • 107. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate, start_txn, enddate, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte 6 measures 7 classifier() as growth_class 8 , first(dte) as startdate 9 , first(cumu_txns) as start_txn 10 , last(dte) as enddate 11 , next(cumu_txns) as end_txn 12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn 13 one row per match after match skip past last row 14 pattern ( fast+ | slow{3,} ) 15 define fast as next(cumu_txns) / cumu_txns >= 1.20 16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and 17 next(slow.cumu_txns) / slow.cumu_txns < 1.20 18 ) 19 order by customer, startdate; 113 SQL> select customer, growth_class, startdate, start_txn, enddate, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte 6 measures 7 classifier() as growth_class 8 , first(dte) as startdate 9 , first(cumu_txns) as start_txn 10 , last(dte) as enddate 11 , next(cumu_txns) as end_txn 12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn 13 one row per match after match skip past last row 14 pattern ( fast+ | slow{2,} ) 15 define fast as next(cumu_txns) / cumu_txns >= 1.20 16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and 17 next(slow.cumu_txns) / slow.cumu_txns < 1.20 18 ) 19 order by customer, startdate;
  • 108. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate, start_txn, enddate, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte ... 114
  • 109. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate, start_txn, enddate, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte ... 115 logical subsets critical as per analytics según el análisis
  • 110. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | patterns 116
  • 111. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 117 SQL> select customer, growth_class, startdate, start_txn, enddate, ... 14 pattern ( fast+ | slow{3,} ) 15 define fast as next(cumu_txns) / cumu_txns >= 1.20 16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and 17 next(slow.cumu_txns) / slow.cumu_txns < 1.20 regular expression syntax
  • 112. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | * + ? {3} {3,} {3,6} {,2} ? 118 0 or more matches 1 or more matches 0 or 1 match exactly 3 matches 3 or more matches between 3 and 6 matches between 0 and 2 matches reluctance
  • 113. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | a|b (a b){3}c permute a b c ^ $ {- a -} 119 a or b 3 times ( a then b ) then c abc,acb,bac,bca,cab,cba first row in pattern last row in pattern (^ p+ $) not a
  • 114. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | reluctance 120 reluctancia
  • 115. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "How long was someone's job?... i.e hired, worked for some time, then fired" 121 http://www.kibeha.dk/2015/07/row-pattern-matching-nested-within.html "¿Cuánto tiempo estuvo el trabajo de alguien? ... es decir Contratado, trabajado por algún tiempo, luego despedido "
  • 116. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t order by 1; SEQ COL ---------- ---------- 1 Hired 2 Worked 3 Worked 4 Worked 5 Worked 6 Worked 7 Terminated 8 Hired 9 Worked 10 Worked 11 Worked 12 Worked 13 Worked 14 Terminated 15 Hired 16 Worked 17 Worked 18 Worked 19 Worked 20 Worked 21 Terminated 122
  • 117. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t order by 1; SEQ COL ---------- ---------- 1 Hired 2 Worked 3 Worked 4 Worked 5 Worked 6 Worked 7 Terminated 8 Hired 9 Worked 10 Worked 11 Worked 12 Worked 13 Worked 14 Terminated 15 Hired 16 Worked 17 Worked 18 Worked 19 Worked 20 Worked 21 Terminated 123
  • 118. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by seq 5 measures 6 first(col) as fcol, 7 col as col, 8 first(seq) p_start, 9 last(seq) p_end, 10 count(*) tot 11 one row per match 12 pattern ( hired worked* fired ) 13 define 14 hired as col = 'Hired', 15 fired as col = 'Terminated' 16 ); FCOL COL P_START P_END TOT ---------- ---------- ---------- ---------- ---------- Hired Terminated 1 21 21 124 "always true" esto siempre es cierto
  • 119. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 125
  • 120. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | greediness 126
  • 121. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t order by 1; SEQ COL ---------- ---------- 1 Hired 2 Worked 3 Worked 4 Worked 5 Worked 6 Worked 7 Terminated 8 Hired 9 Worked 10 Worked 11 Worked 12 Worked 13 Worked 14 Terminated 15 Hired 16 Worked 17 Worked 18 Worked 19 Worked 20 Worked 21 Terminated 127 pattern ( hired worked* fired ) "Cool, I have my 'hired'" "Awesome, I found 'worked' (ie, anything)" "Consume as many rows as I can to see if I can find 'fired'" "Woo Hoo!" He encontrado mi 'Hired' He encontrado mi 'Worked' "Consume tantas registros como puedo ver si puedo encontrar 'Fired'
  • 122. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by seq 5 measures 6 first(col) as fcol, 7 col as col, 8 first(seq) p_start, 9 last(seq) p_end, 10 count(*) tot 11 one row per match 12 pattern ( hired worked*? fired ) 13 define 14 hired as col = 'Hired', 15 fired as col = 'Terminated' ); FCOL COL P_START P_END TOT ---------- ---------- ---------- ---------- ---------- Hired Terminated 1 7 7 Hired Terminated 8 14 7 Hired Terminated 15 21 7 128 reluctantly search
  • 123. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | be careful 129 ten cuidado
  • 124. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 130
  • 125. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t order by 1; SEQ COL ---------- ---------- 1 Hired 2 Worked 3 Worked 4 Worked 5 Worked 6 Worked 7 Terminated 8 Worked 9 Worked 10 Worked 11 Worked 12 Worked 13 Worked 14 Worked 15 Worked 16 Worked 17 Worked 18 Worked 19 Worked 20 Worked 21 Worked 131
  • 126. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by seq 5 measures 6 first(col) as fcol, 7 col as col, 8 first(seq) p_start, ... ORA-4030: Out of process memory when ... 132
  • 127. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by seq 5 measures 6 first(col) as fcol, 7 col as col, 8 first(seq) p_start, 9 last(seq) p_end, 10 count(*) tot 11 one row per match 12 pattern ( hired worked* fired ) 13 define 14 hired as col = 'Hired', 15 worked as col = 'Worked', 15 fired as col = 'Terminated' ); 133 worked+
  • 128. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t order by 1; SEQ COL ---------- ---------- 1 Hired 2 Worked 3 Worked 4 Worked 5 Worked 6 Worked 7 Terminated 8 Hired 9 Worked 10 Worked 11 Worked 12 Worked 13 Worked 14 Terminated 15 Hired 16 Worked 17 Worked 18 Worked 19 Worked 20 Worked 21 Terminated 134 pattern ( hired worked+ fired ) "Cool, I have my 'hired'" "Awesome, I found 'worked'" "worked+ has finished, now look for fired'" He encontrado mi 'Hired' He encontrado mi 'Worked' worked+ ha terminado, ahora busca 'fired'
  • 129. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | “imagination is more important than knowledge” - Albert Einstein 135 "La imaginación es más importante que el conocimiento "
  • 130. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 136 examples ejemplos
  • 131. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "count of my subordinates" 137 http://www.kibeha.dk/2015/07/row-pattern-matching-nested-within.html "cuenta de mis subordinados"
  • 132. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | EMPNO ENAME REPORTS --------- -------------------- ---------- 7839 KING 13 7566 JONES 4 7788 SCOTT 1 7876 ADAMS 0 7902 FORD 1 7369 SMITH 0 7698 BLAKE 5 7499 ALLEN 0 7521 WARD 0 7654 MARTIN 0 7844 TURNER 0 7900 JAMES 0 7782 CLARK 1 7934 MILLER 0 138
  • 133. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 139 conventional style
  • 134. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select empno 2 , lpad(' ', (level-1)*2) || ename as ename 3 , ( select count(*) 4 from emp sub 5 start with sub.mgr = emp.empno 6 connect by sub.mgr = prior sub.empno 7 ) reports 8 from emp 9 start with mgr is null 10 connect by mgr = prior empno 11 order siblings by empno; EMPNO ENAME REPORTS ---------- -------------------- ---------- 7839 KING 13 7566 JONES 4 7788 SCOTT 1 7876 ADAMS 0 7902 FORD 1 ... 140 select count(*) from emp sub start with sub.mgr = emp.empno connect by sub.mgr = prior sub.empno select count(*) from emp sub start with sub.mgr = emp.empno connect by sub.mgr = prior sub.empno select count(*) from emp sub start with sub.mgr = emp.empno connect by sub.mgr = prior sub.empno select count(*) from emp sub start with sub.mgr = emp.empno connect by sub.mgr = prior sub.empno select count(*) from emp sub start with sub.mgr = emp.empno connect by sub.mgr = prior sub.empno
  • 135. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 141 where's the pattern ? SQL> select ... 2 from cust_summary 3 match_recognize ( 4 order by ... 5 pattern ... ... ¿Dónde está el patrón?
  • 136. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 142 ordering sequence
  • 137. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 143 "starting level" "nivel inicial"
  • 138. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 144 "starting level" "next level higher then starting level?" "siguiente nivel más alto entonces nivel inicial?
  • 139. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 145 "starting level" "next level higher then starting level?" "siguiente nivel más alto entonces nivel inicial?
  • 140. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 146 "starting level" "next level higher then starting level?" "siguiente nivel más alto entonces nivel inicial?
  • 141. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 147 "Done! How many?" "¡Listo! ¿Cuántos?"
  • 142. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> with raw_data as ( 2 select lvl, empno, ename, rownum as rn 3 from ( select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ) 8 ) ... 148 as before
  • 143. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ... 9 select empno 10 , lpad(' ', (lvl-1)*2) || ename as ename 11 , reports 12 from raw_data 13 match_recognize ( 14 order by rn 15 measures 16 starting_level.rn as rn 17 , starting_level.lvl as lvl 18 , starting_level.empno as empno 19 , starting_level.ename as ename 20 , count(higher_level.lvl) as reports 21 one row per match 22 after match skip to next row 23 pattern (starting_level higher_level*) 24 define higher_level as lvl > starting_level.lvl 25 ) 26 order by rn; 149
  • 144. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> with raw_data as ( 2 select lvl, empno, ename, rownum as rn 3 from ( select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ) 8 ) 9 select empno 10 , lpad(' ', (lvl-1)*2) || ename as ename 11 , reports 12 from raw_data 13 match_recognize ( 14 order by rn 15 measures 16 starting_level.rn as rn 17 , starting_level.lvl as lvl 18 , starting_level.empno as empno 19 , starting_level.ename as ename 20 , count(higher_level.lvl) as reports 21 one row per match 22 pattern (starting_level higher_level*) 23 define higher_level as lvl > starting_level.lvl 24 ) 25 order by rn; EMPNO ENAME REPORTS ---------- -------------------- ---------- 7839 KING 13 150
  • 145. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 151
  • 146. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 152 recall recordar
  • 147. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 153 found a match encontré una coincidencia X ---------- 1 2 3 5 6 9 10 11 16 17 19 21 30 resume from next row reanudar desde el próximo registro
  • 148. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 154
  • 149. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 155 "done!"
  • 150. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | ... 9 select empno 10 , lpad(' ', (lvl-1)*2) || ename as ename 11 , reports 12 from raw_data 13 match_recognize ( 14 order by rn 15 measures 16 starting_level.rn as rn 17 , starting_level.lvl as lvl 18 , starting_level.empno as empno 19 , starting_level.ename as ename 20 , count(higher_level.lvl) as reports 21 one row per match 22 after match skip to next row 23 pattern (starting_level higher_level*) 24 define higher_level as lvl > starting_level.lvl 25 ) 26 order by rn; 156
  • 151. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select lvl, empno, ename, rownum as rn 2 from ( 3 select level as lvl, empno, ename 4 from emp 5 start with mgr is null 6 connect by mgr = prior empno 7 order siblings by empno ); LVL EMPNO ENAME RN ---------- ---------- -------------------- ---------- 1 7839 KING 1 2 7566 JONES 2 3 7788 SCOTT 3 4 7876 ADAMS 4 3 7902 FORD 5 4 7369 SMITH 6 2 7698 BLAKE 7 3 7499 ALLEN 8 3 7521 WARD 9 3 7654 MARTIN 10 3 7844 TURNER 11 3 7900 JAMES 12 2 7782 CLARK 13 3 7934 MILLER 14 157
  • 152. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> with raw_data as ( ... 13 match_recognize ( 14 order by rn 15 measures 16 starting_level.rn as rn 17 , starting_level.lvl as lvl 18 , starting_level.empno as empno 19 , starting_level.ename as ename 20 , count(higher_level.lvl) as reports 21 one row per match 22 after match skip to next row 23 pattern (starting_level higher_level*) 24 define higher_level as lvl > starting_level.lvl 25 ) 26 order by rn; EMPNO ENAME REPORTS ---------- -------------------- ---------- 7839 KING 13 7566 JONES 4 7788 SCOTT 1 7876 ADAMS 0 7902 FORD 1 7369 SMITH 0 7698 BLAKE 5 7499 ALLEN 0 ... 158
  • 153. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 159 the power of a single SQL un solo SQL tiene mucho poder
  • 154. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |160 select ename from emp where empno = :1 select sum(...) from emp, dept group by ... select min(..) keep ( dense_rank ) ... from emp ... select ... from emp match_recognize measures define ...
  • 155. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 161 what if it doesn't work ? ¿Qué pasa si no funciona?
  • 156. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 162 Requirement "Woo hoo!"
  • 157. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 163 3GL ... we debug usamos depuración
  • 158. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | procedure check_auto_no_new_questions is l_app_controls_rec ate_application_controls%rowtype; l_auto_no_new_limit number; l_new_never_read_cnt number; begin apex_debug.message('Checking metadata'); select * into l_app_controls_rec from ate_application_controls where application_code = 'NONEW'; if l_app_controls_rec.enabled = 'Y' then apex_debug.message('NONEW'); return; end if; apex_debug.message('l_new_never_read_cnt='||l_new_never_read_cnt ); apex_debug.message('l_auto_no_new_limit ='||l_new_never_read_cnt ); if l_new_never_read_cnt >= l_auto_no_new_limit then apex_debug.message('Turning off settings'); update ate_application_controls set enabled = 'Y' where application_code = 'NONEW'; ... 164
  • 159. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select customer, growth_class, startdate, start_txn, enddate, 2 end_txn, avg_daily_txn 3 from cust_summary 4 match_recognize ( 5 partition by customer order by dte 6 measures 7 final last(dte) as termdate 8 , first(dte) as startdate 9 , first(cumu_txns) as start_txn 10 , last(dte) as enddate 11 , next(cumu_txns) as end_txn 12 , (next(cumu_txns) - first(cumu_txns)) / count(*) as avg_daily_txn 13 one row per match after match skip past last row 14 pattern ( fast+ | slow{3,} ) 15 define fast as next(cumu_txns) / cumu_txns >= 1.20 16 , slow as next(slow.cumu_txns) / slow.cumu_txns >= 1.10 and 17 next(slow.cumu_txns) / slow.cumu_txns < 1.20 18 ) 19 order by customer, startdate; 165
  • 160. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 166
  • 161. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | match_number() 167
  • 162. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "Hello World" 168
  • 163. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 , count(*) range 7 one row per match 8 pattern ( starting_row contig* ) 9 define contig as x = prev(x) + 1 ); LO HI RANGE ---------- ---------- ---------- 1 3 3 5 6 2 9 11 3 16 17 2 19 19 1 21 21 1 30 30 1 169
  • 164. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 , count(*) range 7 , match_number() as mn 8 all rows per match 9 pattern ( starting_row contig* ) 10 define contig as x = prev(x) + 1 ); X LO HI RANGE MN ---------- ---------- ---------- ---------- ---------- 1 1 1 1 1 2 1 2 2 1 3 1 3 3 1 5 5 5 1 2 6 5 6 2 2 9 9 9 1 3 10 9 10 2 3 11 9 11 3 3 16 16 16 1 4 17 16 17 2 4 19 19 19 1 5 21 21 21 1 6 30 30 30 1 7 170
  • 165. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | classifier() 171
  • 166. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures 4 first(x) lo 5 , last(x) hi 6 , count(*) range 7 , match_number() as mn 8 , classifier() as cl 9 all rows per match 10 pattern ( starting_row contig* ) 11 define contig as x = prev(x) + 1 ); X LO HI RANGE MN CL ---------- ---------- ---------- ---------- ---------- ------------- 1 1 1 1 1 STARTING_ROW 2 1 2 2 1 CONTIG 3 1 3 3 1 CONTIG 5 5 5 1 2 STARTING_ROW 6 5 6 2 2 CONTIG 9 9 9 1 3 STARTING_ROW 10 9 10 2 3 CONTIG 11 9 11 3 3 CONTIG 16 16 16 1 4 STARTING_ROW 17 16 17 2 4 CONTIG 19 19 19 1 5 STARTING_ROW 21 21 21 1 6 STARTING_ROW 30 30 30 1 7 STARTING_ROW 172
  • 167. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 173 more examples ejemplos
  • 168. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | pattern aggregates as measures 174 patrones agregados como medidas
  • 169. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "W patterns in sales transactions" 175 "Patrones W en transacciones de ventas"
  • 170. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |176
  • 171. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |177 slope1 = amt < prev(amt) slope2 = amt > prev(amt) slope3 = amt < prev(amt) slope4 = amt < prev(amt) pattern = ( slope1+ slope2+ slope3+ slope4+ )
  • 172. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "average AMT in the matched W" 178 "AMT promedio en la W coincidente"
  • 173. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |179 slope1 = amt < prev(amt) slope2 = amt > prev(amt) slope3 = amt < prev(amt) slope4 = amt < prev(amt) pattern = ( slope1+ slope2+ slope3+ slope4+ ) measures avg(amt) as w_average
  • 174. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "average AMT in first downward slide" 180 "AMT promedio en la primera diapositiva descendente"
  • 175. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |181 slope1 = amt < prev(amt) slope2 = amt > prev(amt) slope3 = amt < prev(amt) slope4 = amt < prev(amt) pattern = ( slope1+ slope2+ slope3+ slope4+ ) measures avg(slope1.amt) as slide_avg
  • 176. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | pattern subsets 182 subconjuntos de patrones
  • 177. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "average AMT in first V of the W" 183 "AMT promedio en la primera V de la W"
  • 178. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |184 slope1 = amt < prev(amt) slope2 = amt > prev(amt) slope3 = amt < prev(amt) slope4 = amt < prev(amt) pattern = ( slope1+ slope2+ slope3+ slope4+ ) subset s1s2 = ( slope1,slope2) measures avg(s1s2.amt) as slide_avg
  • 179. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | pattern aggregates as predicates 185 agregados de patrones como predicados
  • 180. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "W patterns in sales transactions, capped at 7 days" 186 "Patrones de W en transacciones de ventas, limitado a los 7 días "
  • 181. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |187 slope1 = amt < prev(amt) slope2 = amt > prev(amt) slope3 = amt < prev(amt) slope4 = amt < prev(amt) and slope4.dte - first(slope1.dte) < 7 Apr 3 Apr 8
  • 182. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 188
  • 183. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "Divides a set of weights into 3 equi-sized buckets" 189 https://stewashton.wordpress.com/2014/06/06/bin-fitting-problems-with-sql/ "Divide un conjunto de pesas en 3 cubos de igual tamaño"
  • 184. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t; KG ---------- 1 3 4 6 7 8 11 12 13 14 17 18 19 190 1 3 4 6 7 8 11 12 13 14 17 18 19
  • 185. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | pattern ( (bin1|bin2|bin3)* ) define bin1 as count(bin1.*) = 1 or sum(bin1.kg) <= least(sum(bin2.kg), sum(bin3.kg) , bin2 as count(bin2.*) = 1 or sum(bin2.kg)-bin2.kg <= sum(bin3.kg) 191 I will want 3 bins (matching my as yet unknown rules) the bin is empty - bin1.kg or my bin has less than either of the other two bins ... so far use my bin if ...
  • 186. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by kg desc 5 measures 6 classifier() bin#, 7 sum(bin1.kg) bin1, 8 sum(bin2.kg) bin2, 9 sum(bin3.kg) bin3 10 all rows per match 11 pattern ( 12 (bin1|bin2|bin3)* 13 ) 14 define 15 bin1 as count(bin1.*) = 1 or 16 sum(bin1.kg)-bin1.kg <= least(sum(bin2.kg), sum(bin3.kg)) 17 , bin2 as count(bin2.*) = 1 or 18 sum(bin2.kg)-bin2.kg <= sum(bin3.kg) 19 ); 192
  • 187. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | KG BIN# BIN1 BIN2 BIN3 ---------- ------ ---------- ---------- ---------- 19 BIN1 19 18 BIN2 19 18 17 BIN3 19 18 17 14 BIN3 19 18 31 13 BIN2 19 31 31 12 BIN1 31 31 31 11 BIN1 42 31 31 8 BIN2 42 39 31 7 BIN3 42 39 38 6 BIN3 42 39 44 4 BIN2 42 43 44 3 BIN1 45 43 44 1 BIN2 45 44 44 193
  • 188. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * 2 from t 3 match_recognize ( 4 order by kg desc 5 measures 6 sum(bin1.kg) bin1, 7 sum(bin2.kg) bin2, 8 sum(bin3.kg) bin3 9 pattern ( 10 (bin1|bin2|bin3)* 11 ) 12 define 13 bin1 as count(bin1.*) = 1 or 14 sum(bin1.kg)-bin1.kg <= least(sum(bin2.kg), sum(bin3.kg)) 15 , bin2 as count(bin2.*) = 1 or 16 sum(bin2.kg)-bin2.kg <= sum(bin3.kg) 17 ); BIN1 BIN2 BIN3 ---------- ---------- ---------- 45 44 44 194
  • 189. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | aggregates as patterns 195 agregados como patrones
  • 190. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "If customers reaches their shipping target, ship the products now. Otherwise ship their products after 30 days" 196 http://www.kibeha.dk/2015/07/row-pattern-matching-nested-within.html "Si los clientes alcanzan su objetivo de envío, envíe los productos ahora. De lo contrario, envíe sus productos después de 30 días "
  • 191. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> desc CUST Name Null? Type ----------------------------- -------- ---------------- CUST_ID NUMBER(38) CUST_NAME VARCHAR2(30) MIN_SHIP_VALUE NUMBER(38) SQL> desc CUST_ORDERS Name Null? Type ----------------------------- -------- ---------------- CUST_ID NUMBER ORDER_NO NUMBER AMT NUMBER(38) SHIP_DATE DATE 197
  • 192. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from cust; CUST_ID CUST_NAME MIN_SHIP_VALUE ---------- ------------------------------ -------------- 1 Cust A 350 2 Cust B 750 SQL> select * 2 from cust_orders co 3 order by cust_id, ship_date, order_no; CUST_ID ORDER_NO AMT SHIP_DATE ---------- ---------- ---------- --------- 1 11 100 31-JAN-17 1 13 10 10-FEB-17 1 12 250 11-FEB-17 1 21 1000 21-FEB-17 1 31 4000 31-MAR-17 2 41 175 31-JAN-17 2 51 100 10-FEB-17 2 42 500 11-FEB-17 2 52 1000 21-FEB-17 2 61 100 31-MAR-17 198
  • 193. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from cust; CUST_ID CUST_NAME MIN_SHIP_VALUE ---------- ------------------------------ -------------- 1 Cust A 350 2 Cust B 750 SQL> select * 2 from cust_orders co 3 order by cust_id, ship_date, order_no; CUST_ID ORDER_NO AMT SHIP_DATE ---------- ---------- ---------- --------- 1 11 100 31-JAN-17 1 13 10 10-FEB-17 1 12 250 11-FEB-17 1 21 1000 21-FEB-17 1 31 4000 31-MAR-17 2 41 175 31-JAN-17 2 51 100 10-FEB-17 2 42 500 11-FEB-17 2 52 1000 21-FEB-17 2 61 100 31-MAR-17 199
  • 194. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from cust; CUST_ID CUST_NAME MIN_SHIP_VALUE ---------- ------------------------------ -------------- 1 Cust A 350 2 Cust B 750 SQL> select * 2 from cust_orders co 3 order by cust_id, ship_date, order_no; CUST_ID ORDER_NO AMT SHIP_DATE ---------- ---------- ---------- --------- 1 11 100 31-JAN-17 1 13 10 10-FEB-17 1 12 250 11-FEB-17 1 21 1000 21-FEB-17 1 31 4000 31-MAR-17 2 41 175 31-JAN-17 2 51 100 10-FEB-17 2 42 500 11-FEB-17 2 52 1000 21-FEB-17 2 61 100 31-MAR-17 200
  • 195. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | pattern 201 "any number under the shipping limit" UNDER_LIMIT* "then hit/exceed the shipping limit" OVER_LIMIT "some might never hit the shipping limit" {0,1} "cualquier número bajo el límite de envío" luego exceden el límite de envío "algunos pueden nunca alcanzar el límite de envío"
  • 196. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | definitions 202 UNDER_LIMIT OVER_LIMIT "rolling" sum(amt) < cust.min_ship_limit "rolling" sum(amt) >= cust.min_ship_limit
  • 197. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | recall 203
  • 198. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from t 2 match_recognize ( order by x 3 measures ... pattern ... 4 DEFINE 5 p1 as x = 1 6 , p2 as first(x) = 1 7 , p3 as last(x) = 1 8 , p4 as prev(x) = 1 9 , p5 as next(x) = 1 10 , p6 as count(*) = 1 11 , p7 as final last(x) = 1 12 , p8 as contig.x = 1 13 , p9 as count(contig.*) = 1 14 ); 204 as per ALL ROWS PER MATCH - this row - first row of match pattern - this row - previous row from this row - next row from this row - count from first to this row - ILLEGAL - this 'contig' row - count from first to this contig row contar desde el primero hasta esta fila
  • 199. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from ( 2 select co.*, c.min_ship_value 3 from cust c, cust_orders co 4 where c.cust_id = co.cust_id 5 ) 6 match_recognize ( 7 partition by cust_id 8 order by ship_date, order_no 9 measures 10 match_number() as mno, 11 classifier() as cls, 12 sum(amt) as tot 13 all rows per match 14 pattern ( under_limit* over_limit{0,1} ) 15 define 16 under_limit as sum(amt) < min_ship_value, 17 over_limit as sum(amt) >= min_ship_value ); CUST_ID SHIP_DATE ORDER_NO MNO CLS TOT AMT MIN_SHIP_VALUE ---------- --------- ---------- ----- --------------- ---------- ---------- -------------- 1 31-JAN-17 11 1 UNDER_LIMIT 100 100 350 1 10-FEB-17 13 1 UNDER_LIMIT 110 10 350 1 11-FEB-17 12 1 OVER_LIMIT 360 250 350 1 21-FEB-17 21 2 OVER_LIMIT 1000 1000 350 1 31-MAR-17 31 3 OVER_LIMIT 4000 4000 350 2 31-JAN-17 41 1 UNDER_LIMIT 175 175 750 2 10-FEB-17 51 1 UNDER_LIMIT 275 100 750 2 11-FEB-17 42 1 OVER_LIMIT 775 500 750 2 21-FEB-17 52 2 OVER_LIMIT 1000 1000 750 2 31-MAR-17 61 3 UNDER_LIMIT 100 100 750 205
  • 200. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | "If customers hit their minimum shipping target, ship that batch now. Otherwise ship their products after 30 days" 206 De lo contrario, envíe sus productos después de 30 días
  • 201. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | SQL> select * from ( 2 select co.*, c.min_ship_value 3 from cust c, cust_orders co 4 where c.cust_id = co.cust_id 5 ) 6 match_recognize ( 7 partition by cust_id 8 order by ship_date, order_no 9 measures 10 match_number() as mno, 11 classifier() as cls, 12 sum(amt) as tot, 13 nvl(final last(over_limit.ship_date), last(ship_date)+30) last_ship_date 14 all rows per match 15 pattern ( under_limit* over_limit{0,1} ) 16 define 17 under_limit as sum(amt) < min_ship_value, 18 over_limit as sum(amt) >= min_ship_value ); 207
  • 202. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 208 wrap up
  • 203. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 209
  • 204. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 210 be patient se paciente
  • 205. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | 211 match_number() classifier() ALL ROWS PER MATCH
  • 206. Copyright © 2016, Oracle and/or its affiliates. All rights reserved. | Thank you! youtube bit.ly/youtube-connor blog bit.ly/blog-connor twitter bit.ly/twitter-connor Gracias!