SlideShare a Scribd company logo
1 of 246
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.
SQLThe meanest, fastest thing out there
Connor McDonald
1
Connor McDonald
3
4
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.
Typical speaker ego slide
youtube tinyurl.com/connor-tube
blog connor-mcdonald.com
twitter @connor_mc_d
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.
6
https://asktom.oracle.com
Copyright © 2017, Oracle and/or its affiliates. All rights reserved.https://asktom.oracle.com/officehours
80 hours of free access / Q&A
8
since Feb
9
why talk about this ?
10
# 1
after all ...
11
12
NoSQL
13
non relational
14
why talk about this
15
# 2
What is cool nowadays
16
MICROSERVICES
17
SQL invented microservices !
18
19
"fine-grained to perform a single function"
"Each service is ... minimal, and complete"
https://en.wikipedia.org/wiki/Microservices
select COUNT(*)
from PEOPLE
where GENDER = 'MALE'
What is cooler nowadays
20
API
21
SQL invented APIs !
22
23
"By abstracting the underlying implementation"
"describes the expected behaviour ... but can have multiple implementations"
https://en.wikipedia.org/wiki/Application_programming_interface
select NAME, STREET_NO, ZIP_CODE
from PEOPLE p,
ADDRESS a
where p.AGE > 50
and p.ADDRESS_ID = a.ADDRESS_ID;
key point
24
this session is not about ...
25
being a smart-ass
26
we can do anything ...
27
SQL> with x( s, ind ) as
2 ( select sud, instr( sud, '.' )
3 from ( select replace(replace(
4 replace(replace(:board,'-'),'|'),' '),chr(10)) sud
5 from dual )
6 union all
7 select substr(s,1,ind-1)||z||substr(s,ind+1)
8 , instr(s,'.',ind+1)
9 from x
10 , ( select to_char( rownum ) z
11 from dual connect by rownum <= 9 ) z
12 where ind > 0
13 and not exists (
14 select null
15 from ( select rownum lp from dual
16 connect by rownum <= 9 )
17 where z = substr(s,trunc((ind-1)/9)*9+lp,1)
28
18 or z = substr(s,mod(ind-1,9)-8+lp*9,1)
19 or z = substr(s,mod(trunc((ind-1)/3),3)*3
20 +trunc((ind-1)/27)*27+lp
21 +trunc((lp-1)/3)*6,1)
22 )
23 ),
24 result as (
25 select s
26 from x
27 where ind = 0 )
28 select
29 regexp_replace(substr(s,(idx-1)*9+1,9),
30 '(...)(...)(...)',
31 '1|2|3')||
32 case when mod(idx,3)=0 then chr(10)||rpad('-',11,'-') end soln
33 from result,
34 ( select level idx
35 from dual
36 connect by level <= 9 )
29
Ack: Anton Scheffer,
https://technology.amis.nl
SQL> variable board varchar2(1000)
SQL> begin :board :=
2 '53.|.7.|...
3 6..|195|...
4 .98|...|.6.
5 -----------
6 8..|.61|..3
7 4..|8.3|..1
8 7..|.2.|..6
9 -----------
10 .6.|...|28.
11 ...|419|..5
12 ...|.8.|.79
13 ';
14 end;
30
5 3 7
6 1 9 5
9 8 6
8 6 1 3
4 8 3 1
7 2 6
6 2 8
4 1 9 5
8 7 9
SOLUTION
-----------
534|678|912
672|195|348
198|342|567
-----------
859|761|423
426|853|791
713|924|856
-----------
961|537|284
287|419|635
345|286|179
-----------
31
sud.sql
32
100%
% of developers that
will need to solve Sudoku
as part of their job
33
100%
% of developers that need
to get real stuff done
real stuff
34
35
1
some controversy...
36
37
DBA
39Public
40Public
DBA stuff matters
41
oc00.sql
42
2
transposition
43
rows to columns, colums to rows
44
"I need sales by product
for each quarter....now"
45
SQL> select product, trunc(txn_date,'Q') mth, sum(quantity) total
3 from SALES
4 group by product,trunc(txn_date,'Q')
5 order by 1,2;
PRODUCT MTH TOTAL
-------------------- --- ----------
CHAINSAW JAN 251473
CHAINSAW APR 254830
CHAINSAW JUL 251994
CHAINSAW OCT 243748
HAMMER JAN 249889
HAMMER APR 256566
HAMMER JUL 252992
HAMMER OCT 249104
SCREW DRIVER JAN 245988
SCREW DRIVER APR 249219
SCREW DRIVER JUL 252128
SCREW DRIVER OCT 244721
SPADE JAN 242434
SPADE APR 254090
SPADE JUL 259613
...
46
47
"That’s wrong!...surely you know
I wanted it ACROSS the page"
48
49
pivot clause
50
SQL> select *
2 from (select product,
3 trunc(txn_date,'Q') mth,
4 quantity
5 from sales )
6 pivot( sum(quantity) for mth in
7 ( 'JAN',
8 'APR',
9 'JUL',
10 'OCT') )
11 order by 1
12 /
PRODUCT 'JAN' 'APR' 'JUL' 'OCT'
-------------------- ---------- ---------- ---------- ----------
CHAINSAW 251473 254830 251994 243748
HAMMER 249889 256566 252992 249104
SCREW DRIVER 245988 249219 252128 244721
SPADE 242434 254090 259613 248428
WHEEL BARROW 243899 249327 252296 254137
51
or ...
52
"That’s wrong!...surely you know
I wanted it DOWN the page"
53
SQL> desc SALES_ACROSS
Name Null? Type
----------------------------- -------- -------------
PRODUCT VARCHAR2(20)
Q1 NUMBER
Q2 NUMBER
Q3 NUMBER
Q4 NUMBER
54
unpivot clause
55
SQL> select *
2 from SALES_ACROSS
3 UNPIVOT
4 ( quantity for quarter in (Q1,Q2,Q3,Q4) )
5 /
PRODUCT QUARTER QUANTITY
-------------------- ------- ----------
CHAINSAW Q1 251473
CHAINSAW Q2 254830
CHAINSAW Q3 251994
CHAINSAW Q4 243748
HAMMER Q1 249889
HAMMER Q2 256566
HAMMER Q3 252992
HAMMER Q4 249104
SCREW DRIVER Q1 245988
SCREW DRIVER Q2 249219
SCREW DRIVER Q3 252128
SCREW DRIVER Q4 244721
...
column values
become "quantity"
column names
become "quarter"
56
elements must be known in advance
57
58
3
query block naming
59
C#, C++ ESB Tuxedo
Weblogic
Stored
Procedure
60
for (int i = 0; i < WinningCombinations.Count; ++i)
{
if (WinningCombinations[i].Investment > 0 &&
WinningCombinations[i].PrimaryDividend > MinDividendDeadHeat)
{
maxDivisor =
Math.Max(maxDivisor, WinningCombinations[i].Divisor);
}
}
for (int i = 0; i < WinningCombinations.Count; ++i)
{
if (WinningCombinations[i].Investment > 0 &&
WinningCombinations[i].PrimaryDividend > MinDividendDeadHeat)
{
WinningCombinations[i].Divisor =
maxDivisor / WinningCombinations[i].Divisor;
sumNewDivisors += WinningCombinations[i].Divisor;
}
}61
no comments
62
63
"C# is self-documenting"
64
"uh huh"
65
SQL can be complex
66
SQL should "self document"
67
query blocks =
self-documenting SQL
68
select emp.*
from emp,
( select trunc(hiredate,'YYYY'), max(empno) empno
from emp
where empno > 0
group by trunc(hiredate,'YYYY') ) x,
( select deptno, avg(sal)
from emp
group by deptno ) y
where x.empno = emp.empno
and y.deptno = emp.deptno
69
Id | Operation | Name |
----------------------------------------------|
0 | SELECT STATEMENT | |
1 | HASH JOIN | |
2 | TABLE ACCESS BY INDEX ROWID | EMP |
3 | NESTED LOOPS | |
4 | VIEW | |
5 | SORT GROUP BY | |
6 | TABLE ACCESS BY INDEX ROWID| EMP |
7 | INDEX FULL SCAN | E2 |
8 | INDEX RANGE SCAN | E1 |
9 | VIEW | |
10 | SORT GROUP BY | |
11 | TABLE ACCESS BY INDEX ROWID | EMP |
12 | INDEX RANGE SCAN | E2 |
70
?
71
select emp.*
from emp,
( select trunc(hiredate,'YYYY'), max(empno) empno
from emp
where empno > 0
group by trunc(hiredate,'YYYY') ) x,
( select deptno, avg(sal)
from emp
group by deptno ) y
where x.empno = emp.empno
and y.deptno = emp.deptno
Id | Operation | Name |
----------------------------------------------|
0 | SELECT STATEMENT | |
1 | HASH JOIN | |
2 | TABLE ACCESS BY INDEX ROWID | EMP |
3 | NESTED LOOPS | |
4 | VIEW | |
5 | SORT GROUP BY | |
6 | TABLE ACCESS BY INDEX ROWID| EMP |
7 | INDEX FULL SCAN | E2 |
8 | INDEX RANGE SCAN | E1 |
9 | VIEW | |
10 | SORT GROUP BY | |
11 | TABLE ACCESS BY INDEX ROWID | EMP |
12 | INDEX RANGE SCAN | E2 |
select emp.*
from emp,
( select /*+ QB_NAME(YR_HIRE) */
trunc(hiredate,'YYYY'), max(empno) empno
from emp
where empno > 0
group by trunc(hiredate,'YYYY') ) x,
( select /*+ QB_NAME(AV_SAL) */
deptno, avg(sal)
from emp
group by deptno ) y
where x.empno = emp.empno
and y.deptno = emp.deptno
72
select emp.*
from emp,
( select /*+ QB_NAME(YR_HIRE) */
trunc(hiredate,'YYYY'), max(empno) empno
from emp
where empno > 0
group by trunc(hiredate,'YYYY') ) x,
( select /*+ QB_NAME(AV_SAL) */
deptno, avg(sal)
from emp
group by deptno ) y
where x.empno = emp.empno
and y.deptno = emp.deptno
Id | Operation | Name | Query Block
----------------------------------------------|--------------
0 | SELECT STATEMENT | |
1 | HASH JOIN | |
2 | TABLE ACCESS BY INDEX ROWID | EMP |
3 | NESTED LOOPS | |
4 | VIEW | |
5 | SORT GROUP BY | |
6 | TABLE ACCESS BY INDEX ROWID| EMP |
7 | INDEX FULL SCAN | E2 |
8 | INDEX RANGE SCAN | E1 |
9 | VIEW | |
10 | SORT GROUP BY | |
11 | TABLE ACCESS BY INDEX ROWID | EMP |
12 | INDEX RANGE SCAN | E2 |
SEL$1
SEL$1
AV_SAL
AV_SAL
AV_SAL
AV_SAL
SEL$1
YR_HIRE
YR_HIRE
YR_HIRE
YR_HIRE
73
74
4
error logging
75
SQL> insert into MY_TABLE
2 select *
3 from MY_WHOPPING_GREAT_FAT_TABLE;
76
MY_WHOPPING_GREAT_FAT_TABLE;
77
78
79
80
81
SQL> insert into MY_TABLE
2 select *
3 from MY_WHOPPING_GREAT_FAT_TABLE;
Elapsed: 06:12:34.00
82
SQL> insert into MY_TABLE
2 select *
3 from MY_WHOPPING_GREAT_FAT_TABLE;
Elapsed: 06:12:34.00
ERROR at line 1:
ORA-01847: day of month must be between 1 and last day of month
83
84
Noooooooo
o !
85
86
and then we do this :-)
SQL> select count(*) from MY_TABLE;
COUNT(*)
----------
0
87
what we want
88
keep successful rows
89
skip / bypass bad rows
90
hard
91
SQL> insert into MY_TABLE
2 select *
3 from MY_WHOPPING_GREAT_FAT_TABLE
4 where "not a duplicate"
5 and "datatypes are ok"
6 and "foreign keys are ok"
7 and "check constraints are ok"
92
SQL> exec DBMS_ERRLOG.CREATE_ERROR_LOG('EMP')
93
ERR$_EMP
94
DBMS_ERRLOG.CREATE_ERROR_LOG (
dml_table_name IN VARCHAR2,
err_log_table_name IN VARCHAR2 := NULL,
err_log_table_owner IN VARCHAR2 := NULL,
...
95
SQL> desc ERR$_EMP
Name Null? Type
----------------------------- -------- ----------------
ORA_ERR_NUMBER$ NUMBER
ORA_ERR_MESG$ VARCHAR2(2000)
ORA_ERR_ROWID$ ROWID
ORA_ERR_OPTYP$ VARCHAR2(2)
ORA_ERR_TAG$ VARCHAR2(2000)
EMPNO VARCHAR2(4000)
ENAME VARCHAR2(4000)
JOB VARCHAR2(4000)
MGR VARCHAR2(4000)
HIREDATE VARCHAR2(4000)
SAL VARCHAR2(4000)
COMM VARCHAR2(4000)
DEPTNO VARCHAR2(4000)
96
97
example
98
SQL> select * from NEW_DATA;
EMPNO SAL DEPTNO
---------- ---------- ----------
1000 5000 20
100X 3550 10
2000 2500 50
7934 4000 20
99
non-numeric
no dept 50
duplicate
SQL> exec dbms_errlog.create_error_log( 'EMP' );
PL/SQL procedure successfully completed.
SQL> insert into EMP (empno,sal,deptno)
2 select empno,sal,deptno
3 from NEW_DATA
4 LOG ERRORS REJECT LIMIT UNLIMITED;
1 row created.
100
50
SQL> select ORA_ERR_OPTYP$ op, ORA_ERR_MESG$, EMPNO
2 from ERR$_EMP
OP ORA_ERR_MESG$ EMPNO
-- ------------------------------------------------------------ -----
I ORA-01722: invalid number 100X
I ORA-02291: integrity constraint (SCOTT.FK_DEPTNO) violated 2000
I ORA-00001: unique constraint (SCOTT.PK_EMP) violated 7934
101
102
5
partitioned outer join
103
104
SQL> select *
2 from timeslots;
HR
--
8
9
10
11
12
13
14
15
16
SQL> select *
2 from bookings;
HR ROOM WHO
------- ---------- -------
8 Room2 PETE
9 Room1 JOHN
11 Room1 MIKE
14 Room2 JILL
15 Room2 JANE
16 Room1 SAM
bookings by hour
105
conventional outer join
106
SQL> SELECT hrs.hr, t1.room, t1.who
2 from timeslots hrs
3 left outer join bookings t1
4 on hrs.hr = t1.hr
5 order by 1
HR ROOM WHO
------- ---------- ----------
8 Room2 PETE
9 Room1 JOHN
10
11 Room1 MIKE
12
13
14 Room2 JILL
15 Room2 JANE
16 Room1 SAM
106
bookings by hour per room
107
108
HR ROOM WHO
------- ---------- ----------
8 Room2 PETE
9
10
11
12
13
14 Room2 JILL
15 Room2 JANE
16
HR ROOM WHO
------- ---------- ----------
8
9 Room1 JOHN
10
11 Room1 MIKE
12
13
14
15
16 Room1 SAM
109
SQL> select *
2 from timeslots;
HR
--
8
9
10
11
12
13
14
15
16
x "Room 1"
x "Room 2"
...
x "Room n"
partitioned outer join
110
SQL> SELECT hrs.hr, t1.room, t1.who
2 FROM bookings t1
3 PARTITION BY (t1.room)
4 RIGHT OUTER JOIN timeslots ON (hrs.hr = t1.hr)
5 order by 1,2
HR ROOM WHO
--------- ---------- ----------
8 Room1
9 Room1 JOHN
10 Room1
11 Room1 MIKE
12 Room1
13 Room1
14 Room1
15 Room1
16 Room1 SAM
8 Room2 PETE
9 Room2
10 Room2
11 Room2
12 Room2
13 Room2
14 Room2 JILL
15 Room2 JANE
16 Room2 111
112
6
subquery factoring
113
common table expressions
114
WITH clause
115
SQL> WITH last_hire AS
2 ( select deptno, max(hiredate)
3 from emp
4 group by deptno
5 )
6 select * from last_hire;
DEPTNO MAX(HIRED
---------- ---------
30 03-DEC-81
20 12-JAN-83
10 23-JAN-82
116
"gee....... more code, same result"
117
WITH last_hire AS
(
select deptno, max(hiredate)
from emp
group by deptno
)
select * from last_hire;
118
why is it cool ?
119
good solution metaphor
120
relational is a rigorous model ...
121
relational is the dominant model ...
122
relational ... can be a pain
123
not our fault
124
Codd & Date
125
"data is represented as mathematical n-ary
relations, an n-ary relation being a subset of the
Cartesian product of n domains."
126
127
procedural, linear world
128
"First, get the total salary paid by each department,
then get the average of these totals,
then list those departments above that average"
129
SQL ?
"First, get the total salary paid by department...
SQL> WITH dept_salaries AS (
2 SELECT dname, SUM(sal) dept_sal
3 FROM emp e, dept d
4 WHERE e.deptno = d.deptno
5 GROUP BY dname),
130
"...then get the average of these totals...
6 avg_sal AS ( SELECT AVG(dept_sal) avsal
7 FROM dept_salaries)
131
"...then list those departments above average."
8 SELECT * FROM dept_salaries d, avg_sal a
9 WHERE d.dept_sal > a.avsal
10 ORDER BY d.dname;
132
SQL> WITH dept_salaries AS (
2 SELECT dname, SUM(sal) dept_sal
3 FROM emp e, dept d
4 WHERE e.deptno = d.deptno
5 GROUP BY dname),
6 avg_sal AS ( SELECT AVG(dept_sal) avsal
7 FROM dept_salaries)
8 SELECT * FROM dept_salaries d, avg_sal a
9 WHERE d.dept_sal > a.avsal
10 ORDER BY d.dname;
133
programmer's approach....
134
... relational solution
135
the "finishing touches"
136
everyone loves JSON
137
recall: partitioned outer join
138
139
SQL> with raw_data as (
2 select
3 hrs.hr,
4 t1.room,
5 t1.who
6 from bookings t1
7 partition by (t1.room)
8 right outer join hrs
9 on (hrs.hr = t1.hr)
10 order by
11 hr, room
12 )
13 select
14 json_arrayagg(
15 json_object(key room||to_char(hr) value who )
16 order by hr ) as meetings
17 from raw_data ;
[{"Room1-08":null},
{"Room1-09":"JOHN"},
{"Room1-10":null},
{"Room1-11":"MIKE"},
{"Room1-12":null},
...
...
{"Room2-14":"JILL"},
{"Room2-15":null},
{"Room2-16":"JANE"}]
140
7
pagination
141
142
"employees by hiredate, recent first"
SQL> select empno, ename, hiredate
2 from emp
3 where rownum <= 5
4 order by hiredate desc;
EMPNO ENAME HIREDATE
---------- ---------- -------------------
7654 MARTIN 28/09/1981 00:00:00
7566 JONES 02/04/1981 00:00:00
7521 WARD 22/02/1981 00:00:00
7499 ALLEN 20/02/1981 00:00:00
7369 SMITH 17/12/1980 00:00:00
143
inline view
144
SQL> select *
2 from (
3 select empno, ename, hiredate
4 from emp
5 order by hiredate desc
6 )
7 where rownum <= 5;
EMPNO ENAME HIREDATE
---------- ---------- ---------
7876 ADAMS 12-JAN-83
7788 SCOTT 09-DEC-82
7934 MILLER 23-JAN-82
7900 JAMES 03-DEC-81
7902 FORD 03-DEC-81
145
SQL> select *
2 from (
3 select
4 empno, ename, hiredate,
5 row_number() over ( order by hiredate desc) rn
6 from emp
7 )
8 where rn <= 5;
146
SQL> select empno, ename, hiredate
2 from emp
3 order by hiredate desc
4 fetch first 5 rows only;
EMPNO ENAME HIREDATE
---------- ---------- ---------
7876 ADAMS 12-JAN-83
7788 SCOTT 09-DEC-82
7934 MILLER 23-JAN-82
7900 JAMES 03-DEC-81
7902 FORD 03-DEC-81
147
148
"TL;DR ... my app can do it"
public static void Paging(Connection conn ) throws Exception
{
PreparedStatement sql_stmt =
conn.prepareStatement(
"select empno, ename, hiredate
from emp
order by hiredate desc");
ResultSet rset = sql_stmt.executeQuery();
int i = 0;
while( rset.next() )
{
...
i = i + 1;
if (i > 5) {
break;
}
}
rset.close();
}
149
demo
151
oc01.sql
let the database know
152
SQL> select *
2 from (
3 select empno, ename, hiredate
4 from emp
5 order by hiredate desc
6 )
7 where rownum <= 5;
153
------------------------------------------------
| Id | Operation | Name | Rows |
------------------------------------------------
| 0 | SELECT STATEMENT | | 5 |
|* 1 | COUNT STOPKEY | | |
| 2 | VIEW | | 14 |
|* 3 | SORT ORDER BY STOPKEY| | 14 |
| 4 | TABLE ACCESS FULL | EMP | 14 |
------------------------------------------------
SQL> select empno, ename, hiredate
2 from emp
3 order by hiredate desc
4 fetch first 5 rows only;
154
-------------------------------------------------
| Id | Operation | Name | Rows |
-------------------------------------------------
| 0 | SELECT STATEMENT | | 14 |
|* 1 | VIEW | | 14 |
|* 2 | WINDOW SORT PUSHED RANK| | 14 |
| 3 | TABLE ACCESS FULL | EMP | 14 |
-------------------------------------------------
you get other benefits
155
oc02.sql
156
"but what about the next page ?"
there
157
is
no
next
page
new query
158
SQL> select empno, ename, hiredate
2 from emp
3 order by hiredate desc
4 offset 5 rows fetch first 5 rows only;
EMPNO ENAME HIREDATE
---------- ---------- ---------
7839 KING 17-NOV-81
7654 MARTIN 28-SEP-81
7844 TURNER 08-SEP-81
7782 CLARK 09-JUN-81
7698 BLAKE 01-MAY-81
159
forget the OFFSET clause
160
SQL> select empno, ename, hiredate
2 from emp
3 order by hiredate desc;
HIREDATE EMPNO ENAME
--------- ---------- --------
12-JAN-83 7876 ADAMS
09-DEC-82 7788 SCOTT
23-JAN-82 7934 MILLER
03-DEC-81 7902 FORD
03-DEC-81 7900 JAMES
17-NOV-81 7839 KING
28-SEP-81 7654 MARTIN
08-SEP-81 7844 TURNER
09-JUN-81 7782 CLARK
01-MAY-81 7698 BLAKE
02-APR-81 7566 JONES
22-FEB-81 7521 WARD
20-FEB-81 7499 ALLEN
17-DEC-80 7369 SMITH
161
fetch first 5 rows
offset 5 fetch next ...
17-FEB-91 7521 BROWN
SQL> select empno, ename, hiredate
2 from emp
3 order by hiredate desc;
HIREDATE EMPNO ENAME
--------- ---------- --------
12-JAN-83 7876 ADAMS
09-DEC-82 7788 SCOTT
23-JAN-82 7934 MILLER
03-DEC-81 7902 FORD
03-DEC-81 7900 JAMES
17-NOV-81 7839 KING
28-SEP-81 7654 MARTIN
08-SEP-81 7844 TURNER
09-JUN-81 7782 CLARK
01-MAY-81 7698 BLAKE
02-APR-81 7566 JONES
22-FEB-81 7521 WARD
20-FEB-81 7499 ALLEN
17-DEC-80 7369 SMITH
162
17-FEB-91 7521 BROWN
SQL> select empno, ename, hiredate
2 from emp
3 where hiredate < :last_shown
3 order by hiredate desc;
163
"an expensive query per page ?!?!
consider result caching
164
SQL> with first_200 as
2 ( select f.*, rownum r
3 from
4 ( select *
5 from t
6 order by owner, object_name desc
7 ) f
8 where rownum <= 200
9 )
10 select *
11 from first_200
12 where r <= 10
165
/*+ result_cache */ rownum r, f.*
oc03.sql
r between 11 and 20
166
8
totals / subtotals
167
"Employee salary list,
plus department total,
plus grand total"
168
169
SQL> select empno, ename, sal, deptno from emp
2 order by deptno;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7782 CLARK 2450 10
7839 KING 5000 10
7934 MILLER 1300 10
...
7900 JAMES 950 30
7698 BLAKE 2850 30
7654 MARTIN 1250 30
170
SQL> select deptno,
2 sum(sal)
3 from emp
4 group by deptno
5 order by deptno;
DEPTNO SUM(SAL)
---------- ----------
10 8750
20 10875
30 9400
SQL> select sum(sal) from emp;
SUM(SAL)
----------
29025
from 3 to 2
171
rollup
SQL> select empno, ename, sal, deptno from emp
2 order by deptno;
EMPNO ENAME SAL DEPTNO
---------- ---------- ---------- ----------
7782 CLARK 2450 10
7839 KING 5000 10
7934 MILLER 1300 10
...
7900 JAMES 950 30
7698 BLAKE 2850 30
7654 MARTIN 1250 30
172
SQL> select deptno,
2 sum(sal)
3 from emp
4 group by rollup(deptno)
5 order by deptno;
DEPTNO SUM(SAL)
---------- ----------
10 8750
20 10875
30 9400
29025
still messy...
173
EMPNO SAL DEPTNO
---------- ---------- ----------
7782 2450 10
7839 5000 10
7934 1300 10
7566 2975 20
7902 3000 20
7876 1100 20
7369 800 20
174
DEPTNO SUM(SAL)
---------- ----------
10 8750
20 10875
30 9400
29025
7782 2450 10
7839 5000 10
7934 1300 10
7566 2975 20
10 8750
from 2 to 1
175
SQL> select deptno,
2 nvl2(rownum,max(empno),null) empno,
3 nvl2(rownum,max(ename),null) ename,
4 sum(sal)
5 from emp
6 group by rollup(deptno,rownum)
7 order by deptno,empno;
DEPTNO EMPNO ENAME SUM(SAL)
---------- ---------- ---------- ----------
10 7782 CLARK 2450
10 7839 KING 5000
10 7934 MILLER 1300
10 8750
20 7369 SMITH 800
20 7566 JONES 2975
...
30 7900 JAMES 950
30 9400
29025176
the whole lot !
177
SQL> select deptno,job,sum(sal) from scott.emp
2 group by CUBE(deptno,job)
3 order by deptno,job;
DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10 8750
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
20 10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30 9400
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
29025
178
totally customisable
179
SQL> select deptno, job, mgr, sum(sal) from emp
2 group by grouping sets (
3 (deptno),
4 (job,mgr), () ) ;
DEPTNO JOB MGR SUM(SAL)
---------- --------- ---------- ----------
CLERK 7902 800
PRESIDENT 5000
CLERK 7698 950
CLERK 7788 1100
CLERK 7782 1300
SALESMAN 7698 5600
MANAGER 7839 8275
ANALYST 7566 6000
10 8750
20 10875
30 9400
29025
180
181
9
pattern matching
182
183
184
185
AML
186
anti money laundering
"Find 10 consecutive deposits in a
24 hour period, then
a withdrawal within three days of
the last deposit, at a different retail outlet"
187
ACCT TSTAMP TYP AMT LOC
---------- ------------------ --- ---------- ----
54261 25/01/13 17:20:55 Dep 100 Perth
54261 25/01/13 17:56:58 Dep 165 Perth
54261 26/01/13 11:24:14 Dep 30 Subiaco
54261 26/01/13 11:47:53 Dep 45 Guildford
54261 26/01/13 12:59:38 Dep 100 Claremont
54261 26/01/13 13:26:04 Dep 80 Perth
54261 26/01/13 14:41:09 Dep 50 Perth
54261 26/01/13 14:53:12 Dep 50 Nedlands
54261 26/01/13 15:15:05 Dep 50 Leederville
54261 26/01/13 15:51:17 Dep 50 Guildford
54261 26/01/13 16:15:02 Dep 120 Perth
54261 26/01/13 16:36:51 Dep 100 Perth
54261 26/01/13 16:55:09 Dep 100 Perth
54261 26/01/13 18:07:17 Wth -500 Nedlands
188
hard...
189
pattern matching
190
SQL> select acct, tstamp, wthd_tstamp, txn_type, amt
2 from account_txns
3 MATCH_RECOGNIZE
4 ( partition by acct
5 order by tstamp
6 measures
7 dep.tstamp dep_tstamp,
8 wthd.tstamp wthd_tstamp
9 all rows per match
10 pattern ( dep{10,} wthd )
11 define
12 dep as
13 txn_type = 'Dep',
14 wthd as
15 txn_type = 'Wth'
16 and last(dep.tstamp)-first(dep.tstamp) < interval '1' day
17 and wthd.tstamp - last(dep.tstamp) < interval '3' day
18 and wthd.location != last(dep.location)
19 )
191
192
https://tinyurl.com/pattern-match
193
10
correlated inline views
194
SQL> desc DEPT_BENEFITS
Name Null? Type
----------------------------- -------- ------------
DEPTNO NUMBER(2)
BONUS NUMBER
BONUS_DATE DATE
SQL> select * from DEPT_BENEFITS
2 order by deptno, bonus_date;
DEPTNO BONUS BONUS_DATE
---------- ---------- ----------
10 10 05-JAN-18
10 12 15-APR-18
20 16 21-AUG-18
20 32 05-SEP-18
30 12 05-AUG-18
30 18 11-NOV-18
40 22 07-FEB-18
40 35 05-AUG-18
195
"show bonus for each employee"
196
SQL> select e.empno, d.deptno, b.bonus
2 from emp e,
3 ( select bonus
4 from DEPT_BENEFITS d
5 where d.deptno = e.deptno
6 ) b
7 order by 1,3;
where d.deptno = e.deptno
*
ERROR at line 5:
ORA-00904: "E"."DEPTNO": invalid identifier
197
<employee>
LATERAL
198
SQL> select e.empno, e.deptno, b.bonus
2 from emp e,
3 LATERAL
4 ( select bonus
5 from DEPT_BENEFITS d
6 where d.deptno = e.deptno
7 ) b
8 order by 1,3;
EMPNO DEPTNO BONUS
---------- ---------- ----------
7369 20 10
7369 20 20
7499 30 10
...
...
"big deal"
200
SQL> select e.empno, d.deptno, b.bonus
2 from emp e,
3 ( select bonus
4 from DEPT_BENEFITS d
5
6 ) b
7
8 order by 1,3;
where d.deptno = e.deptno
201
"best benefit for each employee"
202
SQL> select e.empno, e.deptno, b.bonus
2 from emp e,
3 LATERAL
4 ( select bonus
5 from DEPT_BENEFITS d
6 where d.deptno = e.deptno
7 order by bonus desc
8 fetch first 1 rows only
9 ) b
10 order by 1,3;
EMPNO DEPTNO BENEFITS
---------- ---------- ----------
7369 20 20
7499 30 20
7521 30 20
7566 20 20
7654 30 20
...
203
204
cross-join metadata
SQL> select * from company;
DEPTNO EMPS
---------- -------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
205
3 rows
4 rows
SQL> select c.deptno,
2 regexp_substr(c.emps, '[^,]+', 1, indices.idx) as ename
3 from
4 company c,
5 lateral(
6 select level idx from dual
7 connect by level <=
8 length(regexp_replace(c.emps, '[^,]+')) + 1
9 ) indices;
DEPTNO ENAME
---------- ------------
10 CLARK
10 KING
10 MILLER
20 ADAMS
20 FORD
20 JONES
...
206
207
11
208
almost correct SQL
209
210
background
211
don't you hate ...
212
213
ALERT: Batch load failed
Batch process ended in error.
Module: Financial Reconcilation
Issue: Yearly total
Expected: $7,102,231.76
Actual: $7,102,231.32
214
$7,100,000
$8,200,000
$7,700,000
215
sometimes ...
216
close enough ...
217
... is good enough
218
the hardest work for a database ...
SQL> select count(distinct ...) cdist
2 from my_super_massive_table;
CDIST
-------
12
Elapsed: 01:32:17.00
220
12.1
SQL> select approx_count_distinct(...) cdist
2 from my_super_massive_table;
CDIST
-------
12
Elapsed: 00:12:43.00
222
existing code
223
SQL> select count(*)
2 from user_source
3 where upper(text) like '%COUNT(%DISTINCT%';
COUNT(*)
----------
1723
224
"No thank you"
225
SQL> alter session set approx_for_count_distinct = true;
Session altered.
SQL> select count(distinct ...)
2 from my_super_massive_table;
approx_count_distinct(...)
226
lots of functions
approx_median
approx_percentile
approx_count_distinct_detail
to_approx_...
227
get confidence
228
SQL> select department,
2 approx_median(salary deterministic) med_sal
3 from employees
4 group by department
5 order by department;
DEPARTMENT MED_SAL
---------- -------------
10 4400
20 6000
30 2765
40 6500
229
SQL> select
2 department,
3 approx_median(salary deterministic, 'ERROR_RATE') err
4 from employees
5 group by department
6 order by department;
DEPARTMENT ERR
---------- -------------
10 .002718282
20 .021746255
30 .021746255
40 .002718282
50 .019027973
60 .019027973
230
last
231
232
"talking" to your database
... makes it faster
233
example
234
STORES
CUSTOMERS
SALES
select prod_id, max(amount)
from stores st,
customers c,
sales s
where s.cust_id = c.cust_id(+)
and c.store_id = st.store_id
and s.amount > 10
group by prod_id
235
hash outer join ? nested loop ?
STORES first ?
sort merge ?
---------------------------------------------------
| Id | Operation | Name | Rows |
---------------------------------------------------
| 0 | SELECT STATEMENT | | 100 |
| 1 | HASH GROUP BY | | 100 |
|* 2 | HASH JOIN | | 990K |
| 3 | NESTED LOOPS SEMI | | 5000 |
| 4 | TABLE ACCESS FULL| CUSTOMERS | 5000 |
|* 5 | INDEX UNIQUE SCAN| STORE_IX | 50 |
|* 6 | TABLE ACCESS FULL | SALES | 990K |
---------------------------------------------------
236
237
can we do better ?
add indexes ?
rewrite query ?
result cache ?
materialized view ?
238
share your knowledge with the db
oc04.sql
wrap up
239
SQL
240
very cool
241
very powerful
242
less code
243
never too early to start
244
Enjoy the conference !!!
youtube tinyurl.com/connor-tube
blog connor-mcdonald.com
twitter @connor_mc_d

More Related Content

What's hot (6)

Les00 Intoduction
Les00 IntoductionLes00 Intoduction
Les00 Intoduction
 
Matlab teaching
Matlab teachingMatlab teaching
Matlab teaching
 
Python Lab Manual
Python Lab ManualPython Lab Manual
Python Lab Manual
 
Sq lite functions
Sq lite functionsSq lite functions
Sq lite functions
 
Automated reduction of attack surface using call graph enumeration
Automated reduction of attack surface using call graph enumerationAutomated reduction of attack surface using call graph enumeration
Automated reduction of attack surface using call graph enumeration
 
Airport traffic control simple database model
Airport traffic control simple database modelAirport traffic control simple database model
Airport traffic control simple database model
 

Similar to SQL techniques for faster applications

UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresConnor McDonald
 
Perth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL TechniquesPerth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL TechniquesConnor McDonald
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql featuresConnor McDonald
 
SQL and PLSQL features for APEX Developers
SQL and PLSQL features for APEX DevelopersSQL and PLSQL features for APEX Developers
SQL and PLSQL features for APEX DevelopersConnor McDonald
 
ILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for DevelopersILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for DevelopersConnor McDonald
 
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 MatchingConnor McDonald
 
Dbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineersDbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineersRiyaj Shamsudeen
 
12c for Developers - Feb 2014
12c for Developers - Feb 201412c for Developers - Feb 2014
12c for Developers - Feb 2014Connor McDonald
 
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developersOpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developersConnor McDonald
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresConnor McDonald
 
Connor McDonald 11g for developers
Connor McDonald 11g for developersConnor McDonald 11g for developers
Connor McDonald 11g for developersInSync Conference
 
SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?Andrej Pashchenko
 
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasPostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasJim Mlodgenski
 
A few things about the Oracle optimizer - 2013
A few things about the Oracle optimizer - 2013A few things about the Oracle optimizer - 2013
A few things about the Oracle optimizer - 2013Connor McDonald
 
New SQL features in latest MySQL releases
New SQL features in latest MySQL releasesNew SQL features in latest MySQL releases
New SQL features in latest MySQL releasesGeorgi Sotirov
 
SQL techniques for faster applications
SQL techniques for faster applicationsSQL techniques for faster applications
SQL techniques for faster applicationsConnor McDonald
 
The Five Best Things To Happen To SQL
The Five Best Things To Happen To SQLThe Five Best Things To Happen To SQL
The Five Best Things To Happen To SQLConnor McDonald
 
Demystifying cost based optimization
Demystifying cost based optimizationDemystifying cost based optimization
Demystifying cost based optimizationRiyaj Shamsudeen
 

Similar to SQL techniques for faster applications (20)

UKOUG 2019 - SQL features
UKOUG 2019 - SQL featuresUKOUG 2019 - SQL features
UKOUG 2019 - SQL features
 
Perth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL TechniquesPerth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL Techniques
 
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019  - 10 great sql featuresLatin America Tour 2019  - 10 great sql features
Latin America Tour 2019 - 10 great sql features
 
SQL and PLSQL features for APEX Developers
SQL and PLSQL features for APEX DevelopersSQL and PLSQL features for APEX Developers
SQL and PLSQL features for APEX Developers
 
ILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for DevelopersILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for Developers
 
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
 
Dbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineersDbms plan - A swiss army knife for performance engineers
Dbms plan - A swiss army knife for performance engineers
 
12c for Developers - Feb 2014
12c for Developers - Feb 201412c for Developers - Feb 2014
12c for Developers - Feb 2014
 
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developersOpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL features
 
Connor McDonald 11g for developers
Connor McDonald 11g for developersConnor McDonald 11g for developers
Connor McDonald 11g for developers
 
KScope19 - SQL Features
KScope19 - SQL FeaturesKScope19 - SQL Features
KScope19 - SQL Features
 
SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?SQL Macros - Game Changing Feature for SQL Developers?
SQL Macros - Game Changing Feature for SQL Developers?
 
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and GotchasPostgreSQL Procedural Languages: Tips, Tricks and Gotchas
PostgreSQL Procedural Languages: Tips, Tricks and Gotchas
 
A few things about the Oracle optimizer - 2013
A few things about the Oracle optimizer - 2013A few things about the Oracle optimizer - 2013
A few things about the Oracle optimizer - 2013
 
New SQL features in latest MySQL releases
New SQL features in latest MySQL releasesNew SQL features in latest MySQL releases
New SQL features in latest MySQL releases
 
SQL techniques for faster applications
SQL techniques for faster applicationsSQL techniques for faster applications
SQL techniques for faster applications
 
The Five Best Things To Happen To SQL
The Five Best Things To Happen To SQLThe Five Best Things To Happen To SQL
The Five Best Things To Happen To SQL
 
Oracle
OracleOracle
Oracle
 
Demystifying cost based optimization
Demystifying cost based optimizationDemystifying cost based optimization
Demystifying cost based optimization
 

More from Connor McDonald

Sangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestSangam 19 - PLSQL still the coolest
Sangam 19 - PLSQL still the coolestConnor McDonald
 
Sangam 19 - Analytic SQL
Sangam 19 - Analytic SQLSangam 19 - Analytic SQL
Sangam 19 - Analytic SQLConnor McDonald
 
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 tipsConnor McDonald
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousConnor McDonald
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesConnor McDonald
 
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 autonomousConnor McDonald
 
APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne APAC Groundbreakers 2019 - Perth/Melbourne
APAC Groundbreakers 2019 - Perth/Melbourne Connor McDonald
 
OOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsConnor McDonald
 
OOW19 - Read consistency
OOW19 - Read consistencyOOW19 - Read consistency
OOW19 - Read consistencyConnor McDonald
 
OOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsOOW19 - Slower and less secure applications
OOW19 - Slower and less secure applicationsConnor McDonald
 
OOW19 - Killing database sessions
OOW19 - Killing database sessionsOOW19 - Killing database sessions
OOW19 - Killing database sessionsConnor McDonald
 
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 featuesConnor McDonald
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - FlashbackConnor McDonald
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingConnor McDonald
 
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 processingConnor McDonald
 
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+ optimizerConnor McDonald
 
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 tipsConnor McDonald
 
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 developersConnor McDonald
 

More from Connor McDonald (20)

Flashback ITOUG
Flashback ITOUGFlashback ITOUG
Flashback ITOUG
 
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
 
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
 
Sangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on AutonomousSangam 19 - Successful Applications on Autonomous
Sangam 19 - Successful Applications on Autonomous
 
Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
 
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 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAsOOW19 - Flashback, not just for DBAs
OOW19 - Flashback, not just for DBAs
 
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
 
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
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - Flashback
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matching
 
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
 
ANSI vs Oracle language
ANSI vs Oracle languageANSI vs Oracle language
ANSI vs Oracle language
 
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
 
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
 
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
 

Recently uploaded

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
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 AutomationSafe Software
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
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 2024Rafal Los
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 

Recently uploaded (20)

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
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
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
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
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 

SQL techniques for faster applications

  • 1. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. SQLThe meanest, fastest thing out there Connor McDonald 1
  • 3. 3
  • 4. 4
  • 5. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. Typical speaker ego slide youtube tinyurl.com/connor-tube blog connor-mcdonald.com twitter @connor_mc_d
  • 6. Copyright © 2017, Oracle and/or its affiliates. All rights reserved. 6 https://asktom.oracle.com
  • 7. Copyright © 2017, Oracle and/or its affiliates. All rights reserved.https://asktom.oracle.com/officehours
  • 8. 80 hours of free access / Q&A 8 since Feb
  • 9. 9
  • 10. why talk about this ? 10 # 1
  • 12. 12
  • 14. 14
  • 15. why talk about this 15 # 2
  • 16. What is cool nowadays 16
  • 19. 19 "fine-grained to perform a single function" "Each service is ... minimal, and complete" https://en.wikipedia.org/wiki/Microservices select COUNT(*) from PEOPLE where GENDER = 'MALE'
  • 20. What is cooler nowadays 20
  • 23. 23 "By abstracting the underlying implementation" "describes the expected behaviour ... but can have multiple implementations" https://en.wikipedia.org/wiki/Application_programming_interface select NAME, STREET_NO, ZIP_CODE from PEOPLE p, ADDRESS a where p.AGE > 50 and p.ADDRESS_ID = a.ADDRESS_ID;
  • 25. this session is not about ... 25
  • 27. we can do anything ... 27
  • 28. SQL> with x( s, ind ) as 2 ( select sud, instr( sud, '.' ) 3 from ( select replace(replace( 4 replace(replace(:board,'-'),'|'),' '),chr(10)) sud 5 from dual ) 6 union all 7 select substr(s,1,ind-1)||z||substr(s,ind+1) 8 , instr(s,'.',ind+1) 9 from x 10 , ( select to_char( rownum ) z 11 from dual connect by rownum <= 9 ) z 12 where ind > 0 13 and not exists ( 14 select null 15 from ( select rownum lp from dual 16 connect by rownum <= 9 ) 17 where z = substr(s,trunc((ind-1)/9)*9+lp,1) 28
  • 29. 18 or z = substr(s,mod(ind-1,9)-8+lp*9,1) 19 or z = substr(s,mod(trunc((ind-1)/3),3)*3 20 +trunc((ind-1)/27)*27+lp 21 +trunc((lp-1)/3)*6,1) 22 ) 23 ), 24 result as ( 25 select s 26 from x 27 where ind = 0 ) 28 select 29 regexp_replace(substr(s,(idx-1)*9+1,9), 30 '(...)(...)(...)', 31 '1|2|3')|| 32 case when mod(idx,3)=0 then chr(10)||rpad('-',11,'-') end soln 33 from result, 34 ( select level idx 35 from dual 36 connect by level <= 9 ) 29 Ack: Anton Scheffer, https://technology.amis.nl
  • 30. SQL> variable board varchar2(1000) SQL> begin :board := 2 '53.|.7.|... 3 6..|195|... 4 .98|...|.6. 5 ----------- 6 8..|.61|..3 7 4..|8.3|..1 8 7..|.2.|..6 9 ----------- 10 .6.|...|28. 11 ...|419|..5 12 ...|.8.|.79 13 '; 14 end; 30 5 3 7 6 1 9 5 9 8 6 8 6 1 3 4 8 3 1 7 2 6 6 2 8 4 1 9 5 8 7 9
  • 32. 32 100% % of developers that will need to solve Sudoku as part of their job
  • 33. 33 100% % of developers that need to get real stuff done
  • 35. 35 1
  • 38.
  • 42. 42 2
  • 44. rows to columns, colums to rows 44
  • 45. "I need sales by product for each quarter....now" 45
  • 46. SQL> select product, trunc(txn_date,'Q') mth, sum(quantity) total 3 from SALES 4 group by product,trunc(txn_date,'Q') 5 order by 1,2; PRODUCT MTH TOTAL -------------------- --- ---------- CHAINSAW JAN 251473 CHAINSAW APR 254830 CHAINSAW JUL 251994 CHAINSAW OCT 243748 HAMMER JAN 249889 HAMMER APR 256566 HAMMER JUL 252992 HAMMER OCT 249104 SCREW DRIVER JAN 245988 SCREW DRIVER APR 249219 SCREW DRIVER JUL 252128 SCREW DRIVER OCT 244721 SPADE JAN 242434 SPADE APR 254090 SPADE JUL 259613 ... 46
  • 47. 47
  • 48. "That’s wrong!...surely you know I wanted it ACROSS the page" 48
  • 49. 49
  • 51. SQL> select * 2 from (select product, 3 trunc(txn_date,'Q') mth, 4 quantity 5 from sales ) 6 pivot( sum(quantity) for mth in 7 ( 'JAN', 8 'APR', 9 'JUL', 10 'OCT') ) 11 order by 1 12 / PRODUCT 'JAN' 'APR' 'JUL' 'OCT' -------------------- ---------- ---------- ---------- ---------- CHAINSAW 251473 254830 251994 243748 HAMMER 249889 256566 252992 249104 SCREW DRIVER 245988 249219 252128 244721 SPADE 242434 254090 259613 248428 WHEEL BARROW 243899 249327 252296 254137 51
  • 53. "That’s wrong!...surely you know I wanted it DOWN the page" 53
  • 54. SQL> desc SALES_ACROSS Name Null? Type ----------------------------- -------- ------------- PRODUCT VARCHAR2(20) Q1 NUMBER Q2 NUMBER Q3 NUMBER Q4 NUMBER 54
  • 56. SQL> select * 2 from SALES_ACROSS 3 UNPIVOT 4 ( quantity for quarter in (Q1,Q2,Q3,Q4) ) 5 / PRODUCT QUARTER QUANTITY -------------------- ------- ---------- CHAINSAW Q1 251473 CHAINSAW Q2 254830 CHAINSAW Q3 251994 CHAINSAW Q4 243748 HAMMER Q1 249889 HAMMER Q2 256566 HAMMER Q3 252992 HAMMER Q4 249104 SCREW DRIVER Q1 245988 SCREW DRIVER Q2 249219 SCREW DRIVER Q3 252128 SCREW DRIVER Q4 244721 ... column values become "quantity" column names become "quarter" 56
  • 57. elements must be known in advance 57
  • 58. 58 3
  • 60. C#, C++ ESB Tuxedo Weblogic Stored Procedure 60
  • 61. for (int i = 0; i < WinningCombinations.Count; ++i) { if (WinningCombinations[i].Investment > 0 && WinningCombinations[i].PrimaryDividend > MinDividendDeadHeat) { maxDivisor = Math.Max(maxDivisor, WinningCombinations[i].Divisor); } } for (int i = 0; i < WinningCombinations.Count; ++i) { if (WinningCombinations[i].Investment > 0 && WinningCombinations[i].PrimaryDividend > MinDividendDeadHeat) { WinningCombinations[i].Divisor = maxDivisor / WinningCombinations[i].Divisor; sumNewDivisors += WinningCombinations[i].Divisor; } }61
  • 63. 63
  • 66. SQL can be complex 66
  • 67. SQL should "self document" 67
  • 69. select emp.* from emp, ( select trunc(hiredate,'YYYY'), max(empno) empno from emp where empno > 0 group by trunc(hiredate,'YYYY') ) x, ( select deptno, avg(sal) from emp group by deptno ) y where x.empno = emp.empno and y.deptno = emp.deptno 69
  • 70. Id | Operation | Name | ----------------------------------------------| 0 | SELECT STATEMENT | | 1 | HASH JOIN | | 2 | TABLE ACCESS BY INDEX ROWID | EMP | 3 | NESTED LOOPS | | 4 | VIEW | | 5 | SORT GROUP BY | | 6 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | INDEX FULL SCAN | E2 | 8 | INDEX RANGE SCAN | E1 | 9 | VIEW | | 10 | SORT GROUP BY | | 11 | TABLE ACCESS BY INDEX ROWID | EMP | 12 | INDEX RANGE SCAN | E2 | 70
  • 71. ? 71 select emp.* from emp, ( select trunc(hiredate,'YYYY'), max(empno) empno from emp where empno > 0 group by trunc(hiredate,'YYYY') ) x, ( select deptno, avg(sal) from emp group by deptno ) y where x.empno = emp.empno and y.deptno = emp.deptno Id | Operation | Name | ----------------------------------------------| 0 | SELECT STATEMENT | | 1 | HASH JOIN | | 2 | TABLE ACCESS BY INDEX ROWID | EMP | 3 | NESTED LOOPS | | 4 | VIEW | | 5 | SORT GROUP BY | | 6 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | INDEX FULL SCAN | E2 | 8 | INDEX RANGE SCAN | E1 | 9 | VIEW | | 10 | SORT GROUP BY | | 11 | TABLE ACCESS BY INDEX ROWID | EMP | 12 | INDEX RANGE SCAN | E2 |
  • 72. select emp.* from emp, ( select /*+ QB_NAME(YR_HIRE) */ trunc(hiredate,'YYYY'), max(empno) empno from emp where empno > 0 group by trunc(hiredate,'YYYY') ) x, ( select /*+ QB_NAME(AV_SAL) */ deptno, avg(sal) from emp group by deptno ) y where x.empno = emp.empno and y.deptno = emp.deptno 72 select emp.* from emp, ( select /*+ QB_NAME(YR_HIRE) */ trunc(hiredate,'YYYY'), max(empno) empno from emp where empno > 0 group by trunc(hiredate,'YYYY') ) x, ( select /*+ QB_NAME(AV_SAL) */ deptno, avg(sal) from emp group by deptno ) y where x.empno = emp.empno and y.deptno = emp.deptno
  • 73. Id | Operation | Name | Query Block ----------------------------------------------|-------------- 0 | SELECT STATEMENT | | 1 | HASH JOIN | | 2 | TABLE ACCESS BY INDEX ROWID | EMP | 3 | NESTED LOOPS | | 4 | VIEW | | 5 | SORT GROUP BY | | 6 | TABLE ACCESS BY INDEX ROWID| EMP | 7 | INDEX FULL SCAN | E2 | 8 | INDEX RANGE SCAN | E1 | 9 | VIEW | | 10 | SORT GROUP BY | | 11 | TABLE ACCESS BY INDEX ROWID | EMP | 12 | INDEX RANGE SCAN | E2 | SEL$1 SEL$1 AV_SAL AV_SAL AV_SAL AV_SAL SEL$1 YR_HIRE YR_HIRE YR_HIRE YR_HIRE 73
  • 74. 74 4
  • 76. SQL> insert into MY_TABLE 2 select * 3 from MY_WHOPPING_GREAT_FAT_TABLE; 76 MY_WHOPPING_GREAT_FAT_TABLE;
  • 77. 77
  • 78. 78
  • 79. 79
  • 80. 80
  • 81. 81
  • 82. SQL> insert into MY_TABLE 2 select * 3 from MY_WHOPPING_GREAT_FAT_TABLE; Elapsed: 06:12:34.00 82
  • 83. SQL> insert into MY_TABLE 2 select * 3 from MY_WHOPPING_GREAT_FAT_TABLE; Elapsed: 06:12:34.00 ERROR at line 1: ORA-01847: day of month must be between 1 and last day of month 83
  • 85. 85
  • 86. 86 and then we do this :-)
  • 87. SQL> select count(*) from MY_TABLE; COUNT(*) ---------- 0 87
  • 90. skip / bypass bad rows 90
  • 92. SQL> insert into MY_TABLE 2 select * 3 from MY_WHOPPING_GREAT_FAT_TABLE 4 where "not a duplicate" 5 and "datatypes are ok" 6 and "foreign keys are ok" 7 and "check constraints are ok" 92
  • 95. DBMS_ERRLOG.CREATE_ERROR_LOG ( dml_table_name IN VARCHAR2, err_log_table_name IN VARCHAR2 := NULL, err_log_table_owner IN VARCHAR2 := NULL, ... 95
  • 96. SQL> desc ERR$_EMP Name Null? Type ----------------------------- -------- ---------------- ORA_ERR_NUMBER$ NUMBER ORA_ERR_MESG$ VARCHAR2(2000) ORA_ERR_ROWID$ ROWID ORA_ERR_OPTYP$ VARCHAR2(2) ORA_ERR_TAG$ VARCHAR2(2000) EMPNO VARCHAR2(4000) ENAME VARCHAR2(4000) JOB VARCHAR2(4000) MGR VARCHAR2(4000) HIREDATE VARCHAR2(4000) SAL VARCHAR2(4000) COMM VARCHAR2(4000) DEPTNO VARCHAR2(4000) 96
  • 97. 97
  • 99. SQL> select * from NEW_DATA; EMPNO SAL DEPTNO ---------- ---------- ---------- 1000 5000 20 100X 3550 10 2000 2500 50 7934 4000 20 99 non-numeric no dept 50 duplicate
  • 100. SQL> exec dbms_errlog.create_error_log( 'EMP' ); PL/SQL procedure successfully completed. SQL> insert into EMP (empno,sal,deptno) 2 select empno,sal,deptno 3 from NEW_DATA 4 LOG ERRORS REJECT LIMIT UNLIMITED; 1 row created. 100 50
  • 101. SQL> select ORA_ERR_OPTYP$ op, ORA_ERR_MESG$, EMPNO 2 from ERR$_EMP OP ORA_ERR_MESG$ EMPNO -- ------------------------------------------------------------ ----- I ORA-01722: invalid number 100X I ORA-02291: integrity constraint (SCOTT.FK_DEPTNO) violated 2000 I ORA-00001: unique constraint (SCOTT.PK_EMP) violated 7934 101
  • 102. 102 5
  • 104. 104 SQL> select * 2 from timeslots; HR -- 8 9 10 11 12 13 14 15 16 SQL> select * 2 from bookings; HR ROOM WHO ------- ---------- ------- 8 Room2 PETE 9 Room1 JOHN 11 Room1 MIKE 14 Room2 JILL 15 Room2 JANE 16 Room1 SAM
  • 106. 106 SQL> SELECT hrs.hr, t1.room, t1.who 2 from timeslots hrs 3 left outer join bookings t1 4 on hrs.hr = t1.hr 5 order by 1 HR ROOM WHO ------- ---------- ---------- 8 Room2 PETE 9 Room1 JOHN 10 11 Room1 MIKE 12 13 14 Room2 JILL 15 Room2 JANE 16 Room1 SAM 106
  • 107. bookings by hour per room 107
  • 108. 108 HR ROOM WHO ------- ---------- ---------- 8 Room2 PETE 9 10 11 12 13 14 Room2 JILL 15 Room2 JANE 16 HR ROOM WHO ------- ---------- ---------- 8 9 Room1 JOHN 10 11 Room1 MIKE 12 13 14 15 16 Room1 SAM
  • 109. 109 SQL> select * 2 from timeslots; HR -- 8 9 10 11 12 13 14 15 16 x "Room 1" x "Room 2" ... x "Room n"
  • 111. SQL> SELECT hrs.hr, t1.room, t1.who 2 FROM bookings t1 3 PARTITION BY (t1.room) 4 RIGHT OUTER JOIN timeslots ON (hrs.hr = t1.hr) 5 order by 1,2 HR ROOM WHO --------- ---------- ---------- 8 Room1 9 Room1 JOHN 10 Room1 11 Room1 MIKE 12 Room1 13 Room1 14 Room1 15 Room1 16 Room1 SAM 8 Room2 PETE 9 Room2 10 Room2 11 Room2 12 Room2 13 Room2 14 Room2 JILL 15 Room2 JANE 16 Room2 111
  • 112. 112 6
  • 116. SQL> WITH last_hire AS 2 ( select deptno, max(hiredate) 3 from emp 4 group by deptno 5 ) 6 select * from last_hire; DEPTNO MAX(HIRED ---------- --------- 30 03-DEC-81 20 12-JAN-83 10 23-JAN-82 116
  • 117. "gee....... more code, same result" 117
  • 118. WITH last_hire AS ( select deptno, max(hiredate) from emp group by deptno ) select * from last_hire; 118
  • 119. why is it cool ? 119
  • 121. relational is a rigorous model ... 121
  • 122. relational is the dominant model ... 122
  • 123. relational ... can be a pain 123
  • 126. "data is represented as mathematical n-ary relations, an n-ary relation being a subset of the Cartesian product of n domains." 126
  • 127. 127
  • 129. "First, get the total salary paid by each department, then get the average of these totals, then list those departments above that average" 129 SQL ?
  • 130. "First, get the total salary paid by department... SQL> WITH dept_salaries AS ( 2 SELECT dname, SUM(sal) dept_sal 3 FROM emp e, dept d 4 WHERE e.deptno = d.deptno 5 GROUP BY dname), 130
  • 131. "...then get the average of these totals... 6 avg_sal AS ( SELECT AVG(dept_sal) avsal 7 FROM dept_salaries) 131
  • 132. "...then list those departments above average." 8 SELECT * FROM dept_salaries d, avg_sal a 9 WHERE d.dept_sal > a.avsal 10 ORDER BY d.dname; 132
  • 133. SQL> WITH dept_salaries AS ( 2 SELECT dname, SUM(sal) dept_sal 3 FROM emp e, dept d 4 WHERE e.deptno = d.deptno 5 GROUP BY dname), 6 avg_sal AS ( SELECT AVG(dept_sal) avsal 7 FROM dept_salaries) 8 SELECT * FROM dept_salaries d, avg_sal a 9 WHERE d.dept_sal > a.avsal 10 ORDER BY d.dname; 133
  • 139. 139 SQL> with raw_data as ( 2 select 3 hrs.hr, 4 t1.room, 5 t1.who 6 from bookings t1 7 partition by (t1.room) 8 right outer join hrs 9 on (hrs.hr = t1.hr) 10 order by 11 hr, room 12 ) 13 select 14 json_arrayagg( 15 json_object(key room||to_char(hr) value who ) 16 order by hr ) as meetings 17 from raw_data ; [{"Room1-08":null}, {"Room1-09":"JOHN"}, {"Room1-10":null}, {"Room1-11":"MIKE"}, {"Room1-12":null}, ... ... {"Room2-14":"JILL"}, {"Room2-15":null}, {"Room2-16":"JANE"}]
  • 140. 140 7
  • 142. 142 "employees by hiredate, recent first"
  • 143. SQL> select empno, ename, hiredate 2 from emp 3 where rownum <= 5 4 order by hiredate desc; EMPNO ENAME HIREDATE ---------- ---------- ------------------- 7654 MARTIN 28/09/1981 00:00:00 7566 JONES 02/04/1981 00:00:00 7521 WARD 22/02/1981 00:00:00 7499 ALLEN 20/02/1981 00:00:00 7369 SMITH 17/12/1980 00:00:00 143
  • 145. SQL> select * 2 from ( 3 select empno, ename, hiredate 4 from emp 5 order by hiredate desc 6 ) 7 where rownum <= 5; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 12-JAN-83 7788 SCOTT 09-DEC-82 7934 MILLER 23-JAN-82 7900 JAMES 03-DEC-81 7902 FORD 03-DEC-81 145
  • 146. SQL> select * 2 from ( 3 select 4 empno, ename, hiredate, 5 row_number() over ( order by hiredate desc) rn 6 from emp 7 ) 8 where rn <= 5; 146
  • 147. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc 4 fetch first 5 rows only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7876 ADAMS 12-JAN-83 7788 SCOTT 09-DEC-82 7934 MILLER 23-JAN-82 7900 JAMES 03-DEC-81 7902 FORD 03-DEC-81 147
  • 148. 148 "TL;DR ... my app can do it"
  • 149. public static void Paging(Connection conn ) throws Exception { PreparedStatement sql_stmt = conn.prepareStatement( "select empno, ename, hiredate from emp order by hiredate desc"); ResultSet rset = sql_stmt.executeQuery(); int i = 0; while( rset.next() ) { ... i = i + 1; if (i > 5) { break; } } rset.close(); } 149
  • 150.
  • 152. let the database know 152
  • 153. SQL> select * 2 from ( 3 select empno, ename, hiredate 4 from emp 5 order by hiredate desc 6 ) 7 where rownum <= 5; 153 ------------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------------ | 0 | SELECT STATEMENT | | 5 | |* 1 | COUNT STOPKEY | | | | 2 | VIEW | | 14 | |* 3 | SORT ORDER BY STOPKEY| | 14 | | 4 | TABLE ACCESS FULL | EMP | 14 | ------------------------------------------------
  • 154. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc 4 fetch first 5 rows only; 154 ------------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | |* 2 | WINDOW SORT PUSHED RANK| | 14 | | 3 | TABLE ACCESS FULL | EMP | 14 | -------------------------------------------------
  • 155. you get other benefits 155 oc02.sql
  • 156. 156 "but what about the next page ?"
  • 159. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc 4 offset 5 rows fetch first 5 rows only; EMPNO ENAME HIREDATE ---------- ---------- --------- 7839 KING 17-NOV-81 7654 MARTIN 28-SEP-81 7844 TURNER 08-SEP-81 7782 CLARK 09-JUN-81 7698 BLAKE 01-MAY-81 159
  • 160. forget the OFFSET clause 160
  • 161. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc; HIREDATE EMPNO ENAME --------- ---------- -------- 12-JAN-83 7876 ADAMS 09-DEC-82 7788 SCOTT 23-JAN-82 7934 MILLER 03-DEC-81 7902 FORD 03-DEC-81 7900 JAMES 17-NOV-81 7839 KING 28-SEP-81 7654 MARTIN 08-SEP-81 7844 TURNER 09-JUN-81 7782 CLARK 01-MAY-81 7698 BLAKE 02-APR-81 7566 JONES 22-FEB-81 7521 WARD 20-FEB-81 7499 ALLEN 17-DEC-80 7369 SMITH 161 fetch first 5 rows offset 5 fetch next ... 17-FEB-91 7521 BROWN
  • 162. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc; HIREDATE EMPNO ENAME --------- ---------- -------- 12-JAN-83 7876 ADAMS 09-DEC-82 7788 SCOTT 23-JAN-82 7934 MILLER 03-DEC-81 7902 FORD 03-DEC-81 7900 JAMES 17-NOV-81 7839 KING 28-SEP-81 7654 MARTIN 08-SEP-81 7844 TURNER 09-JUN-81 7782 CLARK 01-MAY-81 7698 BLAKE 02-APR-81 7566 JONES 22-FEB-81 7521 WARD 20-FEB-81 7499 ALLEN 17-DEC-80 7369 SMITH 162 17-FEB-91 7521 BROWN SQL> select empno, ename, hiredate 2 from emp 3 where hiredate < :last_shown 3 order by hiredate desc;
  • 163. 163 "an expensive query per page ?!?!
  • 165. SQL> with first_200 as 2 ( select f.*, rownum r 3 from 4 ( select * 5 from t 6 order by owner, object_name desc 7 ) f 8 where rownum <= 200 9 ) 10 select * 11 from first_200 12 where r <= 10 165 /*+ result_cache */ rownum r, f.* oc03.sql r between 11 and 20
  • 166. 166 8
  • 168. "Employee salary list, plus department total, plus grand total" 168
  • 169. 169
  • 170. SQL> select empno, ename, sal, deptno from emp 2 order by deptno; EMPNO ENAME SAL DEPTNO ---------- ---------- ---------- ---------- 7782 CLARK 2450 10 7839 KING 5000 10 7934 MILLER 1300 10 ... 7900 JAMES 950 30 7698 BLAKE 2850 30 7654 MARTIN 1250 30 170 SQL> select deptno, 2 sum(sal) 3 from emp 4 group by deptno 5 order by deptno; DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 9400 SQL> select sum(sal) from emp; SUM(SAL) ---------- 29025
  • 171. from 3 to 2 171 rollup
  • 172. SQL> select empno, ename, sal, deptno from emp 2 order by deptno; EMPNO ENAME SAL DEPTNO ---------- ---------- ---------- ---------- 7782 CLARK 2450 10 7839 KING 5000 10 7934 MILLER 1300 10 ... 7900 JAMES 950 30 7698 BLAKE 2850 30 7654 MARTIN 1250 30 172 SQL> select deptno, 2 sum(sal) 3 from emp 4 group by rollup(deptno) 5 order by deptno; DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 9400 29025
  • 174. EMPNO SAL DEPTNO ---------- ---------- ---------- 7782 2450 10 7839 5000 10 7934 1300 10 7566 2975 20 7902 3000 20 7876 1100 20 7369 800 20 174 DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 9400 29025 7782 2450 10 7839 5000 10 7934 1300 10 7566 2975 20 10 8750
  • 175. from 2 to 1 175
  • 176. SQL> select deptno, 2 nvl2(rownum,max(empno),null) empno, 3 nvl2(rownum,max(ename),null) ename, 4 sum(sal) 5 from emp 6 group by rollup(deptno,rownum) 7 order by deptno,empno; DEPTNO EMPNO ENAME SUM(SAL) ---------- ---------- ---------- ---------- 10 7782 CLARK 2450 10 7839 KING 5000 10 7934 MILLER 1300 10 8750 20 7369 SMITH 800 20 7566 JONES 2975 ... 30 7900 JAMES 950 30 9400 29025176
  • 177. the whole lot ! 177
  • 178. SQL> select deptno,job,sum(sal) from scott.emp 2 group by CUBE(deptno,job) 3 order by deptno,job; DEPTNO JOB SUM(SAL) ---------- --------- ---------- 10 CLERK 1300 10 MANAGER 2450 10 PRESIDENT 5000 10 8750 20 ANALYST 6000 20 CLERK 1900 20 MANAGER 2975 20 10875 30 CLERK 950 30 MANAGER 2850 30 SALESMAN 5600 30 9400 ANALYST 6000 CLERK 4150 MANAGER 8275 PRESIDENT 5000 SALESMAN 5600 29025 178
  • 180. SQL> select deptno, job, mgr, sum(sal) from emp 2 group by grouping sets ( 3 (deptno), 4 (job,mgr), () ) ; DEPTNO JOB MGR SUM(SAL) ---------- --------- ---------- ---------- CLERK 7902 800 PRESIDENT 5000 CLERK 7698 950 CLERK 7788 1100 CLERK 7782 1300 SALESMAN 7698 5600 MANAGER 7839 8275 ANALYST 7566 6000 10 8750 20 10875 30 9400 29025 180
  • 181. 181 9
  • 183. 183
  • 184. 184
  • 185. 185
  • 187. "Find 10 consecutive deposits in a 24 hour period, then a withdrawal within three days of the last deposit, at a different retail outlet" 187
  • 188. ACCT TSTAMP TYP AMT LOC ---------- ------------------ --- ---------- ---- 54261 25/01/13 17:20:55 Dep 100 Perth 54261 25/01/13 17:56:58 Dep 165 Perth 54261 26/01/13 11:24:14 Dep 30 Subiaco 54261 26/01/13 11:47:53 Dep 45 Guildford 54261 26/01/13 12:59:38 Dep 100 Claremont 54261 26/01/13 13:26:04 Dep 80 Perth 54261 26/01/13 14:41:09 Dep 50 Perth 54261 26/01/13 14:53:12 Dep 50 Nedlands 54261 26/01/13 15:15:05 Dep 50 Leederville 54261 26/01/13 15:51:17 Dep 50 Guildford 54261 26/01/13 16:15:02 Dep 120 Perth 54261 26/01/13 16:36:51 Dep 100 Perth 54261 26/01/13 16:55:09 Dep 100 Perth 54261 26/01/13 18:07:17 Wth -500 Nedlands 188
  • 191. SQL> select acct, tstamp, wthd_tstamp, txn_type, amt 2 from account_txns 3 MATCH_RECOGNIZE 4 ( partition by acct 5 order by tstamp 6 measures 7 dep.tstamp dep_tstamp, 8 wthd.tstamp wthd_tstamp 9 all rows per match 10 pattern ( dep{10,} wthd ) 11 define 12 dep as 13 txn_type = 'Dep', 14 wthd as 15 txn_type = 'Wth' 16 and last(dep.tstamp)-first(dep.tstamp) < interval '1' day 17 and wthd.tstamp - last(dep.tstamp) < interval '3' day 18 and wthd.location != last(dep.location) 19 ) 191
  • 193. 193 10
  • 195. SQL> desc DEPT_BENEFITS Name Null? Type ----------------------------- -------- ------------ DEPTNO NUMBER(2) BONUS NUMBER BONUS_DATE DATE SQL> select * from DEPT_BENEFITS 2 order by deptno, bonus_date; DEPTNO BONUS BONUS_DATE ---------- ---------- ---------- 10 10 05-JAN-18 10 12 15-APR-18 20 16 21-AUG-18 20 32 05-SEP-18 30 12 05-AUG-18 30 18 11-NOV-18 40 22 07-FEB-18 40 35 05-AUG-18 195
  • 196. "show bonus for each employee" 196
  • 197. SQL> select e.empno, d.deptno, b.bonus 2 from emp e, 3 ( select bonus 4 from DEPT_BENEFITS d 5 where d.deptno = e.deptno 6 ) b 7 order by 1,3; where d.deptno = e.deptno * ERROR at line 5: ORA-00904: "E"."DEPTNO": invalid identifier 197 <employee>
  • 199. SQL> select e.empno, e.deptno, b.bonus 2 from emp e, 3 LATERAL 4 ( select bonus 5 from DEPT_BENEFITS d 6 where d.deptno = e.deptno 7 ) b 8 order by 1,3; EMPNO DEPTNO BONUS ---------- ---------- ---------- 7369 20 10 7369 20 20 7499 30 10 ... ...
  • 201. SQL> select e.empno, d.deptno, b.bonus 2 from emp e, 3 ( select bonus 4 from DEPT_BENEFITS d 5 6 ) b 7 8 order by 1,3; where d.deptno = e.deptno 201
  • 202. "best benefit for each employee" 202
  • 203. SQL> select e.empno, e.deptno, b.bonus 2 from emp e, 3 LATERAL 4 ( select bonus 5 from DEPT_BENEFITS d 6 where d.deptno = e.deptno 7 order by bonus desc 8 fetch first 1 rows only 9 ) b 10 order by 1,3; EMPNO DEPTNO BENEFITS ---------- ---------- ---------- 7369 20 20 7499 30 20 7521 30 20 7566 20 20 7654 30 20 ... 203
  • 205. SQL> select * from company; DEPTNO EMPS ---------- ------------------------------------- 10 CLARK,KING,MILLER 20 ADAMS,FORD,JONES,SCOTT,SMITH 30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD 205 3 rows 4 rows
  • 206. SQL> select c.deptno, 2 regexp_substr(c.emps, '[^,]+', 1, indices.idx) as ename 3 from 4 company c, 5 lateral( 6 select level idx from dual 7 connect by level <= 8 length(regexp_replace(c.emps, '[^,]+')) + 1 9 ) indices; DEPTNO ENAME ---------- ------------ 10 CLARK 10 KING 10 MILLER 20 ADAMS 20 FORD 20 JONES ... 206
  • 207. 207 11
  • 209. 209
  • 212. 212
  • 213. 213 ALERT: Batch load failed Batch process ended in error. Module: Financial Reconcilation Issue: Yearly total Expected: $7,102,231.76 Actual: $7,102,231.32
  • 217. 217 ... is good enough
  • 218. 218 the hardest work for a database ...
  • 219. SQL> select count(distinct ...) cdist 2 from my_super_massive_table; CDIST ------- 12 Elapsed: 01:32:17.00
  • 221. SQL> select approx_count_distinct(...) cdist 2 from my_super_massive_table; CDIST ------- 12 Elapsed: 00:12:43.00
  • 223. 223 SQL> select count(*) 2 from user_source 3 where upper(text) like '%COUNT(%DISTINCT%'; COUNT(*) ---------- 1723
  • 225. 225 SQL> alter session set approx_for_count_distinct = true; Session altered. SQL> select count(distinct ...) 2 from my_super_massive_table; approx_count_distinct(...)
  • 228. 228 SQL> select department, 2 approx_median(salary deterministic) med_sal 3 from employees 4 group by department 5 order by department; DEPARTMENT MED_SAL ---------- ------------- 10 4400 20 6000 30 2765 40 6500
  • 229. 229 SQL> select 2 department, 3 approx_median(salary deterministic, 'ERROR_RATE') err 4 from employees 5 group by department 6 order by department; DEPARTMENT ERR ---------- ------------- 10 .002718282 20 .021746255 30 .021746255 40 .002718282 50 .019027973 60 .019027973
  • 231. 231
  • 232. 232 "talking" to your database ... makes it faster
  • 235. select prod_id, max(amount) from stores st, customers c, sales s where s.cust_id = c.cust_id(+) and c.store_id = st.store_id and s.amount > 10 group by prod_id 235 hash outer join ? nested loop ? STORES first ? sort merge ?
  • 236. --------------------------------------------------- | Id | Operation | Name | Rows | --------------------------------------------------- | 0 | SELECT STATEMENT | | 100 | | 1 | HASH GROUP BY | | 100 | |* 2 | HASH JOIN | | 990K | | 3 | NESTED LOOPS SEMI | | 5000 | | 4 | TABLE ACCESS FULL| CUSTOMERS | 5000 | |* 5 | INDEX UNIQUE SCAN| STORE_IX | 50 | |* 6 | TABLE ACCESS FULL | SALES | 990K | --------------------------------------------------- 236
  • 237. 237 can we do better ? add indexes ? rewrite query ? result cache ? materialized view ?
  • 238. 238 share your knowledge with the db oc04.sql
  • 244. never too early to start 244
  • 245.
  • 246. Enjoy the conference !!! youtube tinyurl.com/connor-tube blog connor-mcdonald.com twitter @connor_mc_d