SlideShare a Scribd company logo
KScope19 - SQL Features
Copyright Š 2017, Oracle and/or its affiliates. All rights reserved.
SQLThe meanest, fastest thing out there
Connor McDonald
2
Copyright Š 2018, Oracle and/or its affiliates. All rights reserved.
Connor McDonald
Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |
4
Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |
5
Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |
Stuff
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
rants and raves on tech and the world :-)
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. |Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |
https://asktom.oracle.com
9
SO
THE
BIG
QUESTION
IS
15
WHY ?
why talk about SQL ?
16
after all ...
17
18
why talk about SQL # 1
19
NoSQL
20
non relational
21
why talk about SQL # 2
22
developers love cool stuff
23
MICROSERVICES
24
SQL is microservices !
25
26
"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'
even cooler stuff
27
API
28
SQL is entirely APIs !
29
30
"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;
why talk about SQL # 3
31
developers
32
code for functionality ...
33
... yet we end up data processing :-(
34
35
key point
36
this session is not about ...
37
being a smart-ass
38
we can do anything ...
39
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)
40
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 )
41
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;
42
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
-----------
43
sud.sql
44
100%
% of developers that
will need to solve Sudoku
as part of their job
45
100%
% of developers that need
to get real stuff done
real stuff
46
47
1
some controversy...
48
49
DBA
KScope19 - SQL Features
51Public
52Public
DBA friendship is important
53
oc00.sql
54
2
totals / subtotals
55
"Employee salary list,
plus department total,
plus grand total"
56
57
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
58
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
59
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
60
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...
61
EMPNO SAL DEPTNO
---------- ---------- ----------
7782 2450 10
7839 5000 10
7934 1300 10
7566 2975 20
7902 3000 20
7876 1100 20
7369 800 20
62
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
63
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
2902564
all totals are possible
65
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
66
totally customisable
67
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
68
69
3
query block naming
70
C#, C++ ESB Tuxedo
Weblogic
Stored
Procedure
71
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;
}
}72
no comments
73
74
"C# is self-documenting"
75
"uh huh"
76
SQL can be complex
77
SQL should "self document"
78
query blocks =
self documenting SQL
79
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
80
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 |
81
?
82
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
83
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
84
85
4
error logging
86
SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_GREAT_FAT_TABLE;
87
MY_HUGE_GREAT_FAT_TABLE;
88
89
90
91
92
SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_GREAT_FAT_TABLE;
Elapsed: 06:12:34.00
93
SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_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
94
95
96
97
and then we do this :-)
SQL> select count(*) from MY_TABLE;
COUNT(*)
----------
0
98
what we want
99
keep successful rows
100
skip / bypass bad rows
101
hard
102
SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_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"
103
SQL> exec DBMS_ERRLOG.CREATE_ERROR_LOG('EMP')
104
ERR$_EMP
105
DBMS_ERRLOG.CREATE_ERROR_LOG (
dml_table_name IN VARCHAR2,
err_log_table_name IN VARCHAR2 := NULL,
err_log_table_owner IN VARCHAR2 := NULL,
...
106
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)
107
108
example
109
add to EMP from NEW_DATA
110
SQL> select * from NEW_DATA;
EMPNO SAL DEPTNO
---------- ---------- ----------
1000 5000 20
100X 3550 10
2000 2500 50
7934 4000 20
111
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.
112
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
113
114
5
partitioned outer join
115
116
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
117
conventional outer join
118
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
118
bookings by hour per room
119
120
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
121
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
122
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 123
124
6
subquery factoring
125
common table expressions
126
WITH clause
127
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
128
"who cares?....... more code, same result"
129
WITH last_hire AS
(
select deptno, max(hiredate)
from emp
group by deptno
)
select * from last_hire;
130
why is it cool ?
131
good solution metaphor
132
relational is a rigorous model ...
133
relational is the dominant model ...
134
relational ... can sortta suck
135
not our fault
136
Codd & Date
137
"data is represented as mathematical n-ary
relations, an n-ary relation being a subset of the
Cartesian product of n domains."
138
139
procedural world
140
step by step
141
"First, get the total salary paid by each department,
then get the average of these totals,
then list those departments above that average"
142
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),
143
"...then get the average of these totals...
6 avg_sal AS ( SELECT AVG(dept_sal) avsal
7 FROM dept_salaries)
144
"...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;
145
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;
146
programmer's approach....
147
... relational solution
148
the "finishing touches"
149
everyone loves JSON
150
recall: partitioned outer join
151
152
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"}]
153
7
pagination
154
155
"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
156
inline view
157
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
158
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;
159
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
160
161
"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();
}
162
KScope19 - SQL Features
demo
164
oc01.sql
let the database know
165
SQL> select *
2 from (
3 select empno, ename, hiredate
4 from emp
5 order by hiredate desc
6 )
7 where rownum <= 5;
166
------------------------------------------------
| 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;
167
-------------------------------------------------
| 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
168
oc02.sql
169
"but what about the next page ?"
170
forget
the
next
page
new query
171
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
172
forget the OFFSET clause
173
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
174
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
175
17-FEB-91 7521 BROWN
SQL> select empno, ename, hiredate
2 from emp
3 where hiredate < :last_shown
3 order by hiredate desc;
176
"an expensive query per page ?!?!
consider result caching
177
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
178
/*+ result_cache */ rownum r, f.*
oc03.sql
r between 11 and 20
179
8
we all know about analytics
180
SQL> select row_number() OVER ( order by sal )
2 from emp
3 ...
181
https://bit.ly/analytic_sql
182
“Show me lowest salary for each department...”
SQL> select deptno, min(sal)
2 from emp
3 group by deptno;
“...and I need to know who has that
lowest salary as well”
SQL> select deptno, empno, min(sal)
2 from emp
3 group by deptno;
ORA-00979: not a GROUP BY expression
KEEP extension
183
SQL> select deptno, min(sal), min(empno)
2 KEEP ( dense_rank FIRST order by sal) empno
3 from emp
4 group by deptno
5 /
DEPTNO MIN(SAL) EMPNO
---------- ---------- ----------
10 1300 7934
20 800 7369
30 950 7900
Emp 7934 has the
lowest salary in dept 10
184
185
nearly
done!
pattern matching
186
187
188
189
AML
190
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"
191
ACCT TSTAMP TYP AMT LOC
---------- ------------------ ---------- ------- ----
54261 25/01/19 17:20:55 Deposit 100 Perth
54261 25/01/19 17:56:58 Deposit 165 Perth
54261 26/01/19 11:24:14 Deposit 30 Subiaco
54261 26/01/19 11:47:53 Deposit 45 Guildford
54261 26/01/19 12:59:38 Deposit 100 Claremont
54261 26/01/19 13:26:04 Deposit 80 Perth
54261 26/01/19 14:41:09 Deposit 50 Perth
54261 26/01/19 14:53:12 Deposit 50 Nedlands
54261 26/01/19 15:15:05 Deposit 50 Leederville
54261 26/01/19 15:51:17 Deposit 50 Guildford
54261 26/01/19 16:15:02 Deposit 120 Perth
54261 26/01/19 16:36:51 Deposit 100 Perth
54261 26/01/19 16:55:09 Deposit 100 Perth
54261 26/01/19 18:07:17 Withdrawal -500 Nedlands
192
hard ...
193
pattern matching
194
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 = 'Deposit',
14 wthd as
15 txn_type = 'Withdrawal'
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 ) 195
196
https://tinyurl.com/pattern-match
197
last
198
199
"talking" to your database
... makes it faster
200
example
201
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
202
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 |
---------------------------------------------------
203
204
can we do better ?
add indexes ?
rewrite query ?
result cache ?
materialized view ?
205
share your knowledge with the db
oc04.sql
wrap up
206
SQL
207
very cool
208
very powerful
209
less code
210
never too early to start
211
KScope19 - SQL Features
Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |
That's a wrap!
youtube bit.ly/youtube-connor
blog bit.ly/blog-connor
twitter bit.ly/twitter-connor

More Related Content

What's hot (20)

PDF
UKOUG 2019 - SQL features
Connor McDonald
 
PDF
Pattern Matching with SQL - APEX World Rotterdam 2019
Connor McDonald
 
PDF
Latin America Tour 2019 - pattern matching
Connor McDonald
 
PPTX
SQL techniques for faster applications
Connor McDonald
 
PDF
UKOUG - 25 years of hints and tips
Connor McDonald
 
PPTX
Perth APAC Groundbreakers tour - SQL Techniques
Connor McDonald
 
PDF
ANSI vs Oracle language
Connor McDonald
 
PDF
Flashback ITOUG
Connor McDonald
 
PDF
Latin America tour 2019 - Flashback
Connor McDonald
 
PDF
Agile Database Development with JSON
Chris Saxon
 
PPTX
The Five Best Things To Happen To SQL
Connor McDonald
 
KEY
実践 memcached
Masahiro Nagano
 
PDF
Demystifying cost based optimization
Riyaj Shamsudeen
 
PPTX
Get your moneys worth out of your database
Patrick Barel
 
PDF
Oracle Database 12c Application Development
Saurabh K. Gupta
 
PDF
Extreme JavaScript Performance
Thomas Fuchs
 
PPTX
Down the rabbit hole, profiling in Django
Remco Wendt
 
PPTX
JPoint 2016 - Валеев Тагир - Странности Stream API
tvaleev
 
PDF
Using Optimizer Hints to Improve MySQL Query Performance
oysteing
 
PDF
Rich and Snappy Apps (No Scaling Required)
Thomas Fuchs
 
UKOUG 2019 - SQL features
Connor McDonald
 
Pattern Matching with SQL - APEX World Rotterdam 2019
Connor McDonald
 
Latin America Tour 2019 - pattern matching
Connor McDonald
 
SQL techniques for faster applications
Connor McDonald
 
UKOUG - 25 years of hints and tips
Connor McDonald
 
Perth APAC Groundbreakers tour - SQL Techniques
Connor McDonald
 
ANSI vs Oracle language
Connor McDonald
 
Flashback ITOUG
Connor McDonald
 
Latin America tour 2019 - Flashback
Connor McDonald
 
Agile Database Development with JSON
Chris Saxon
 
The Five Best Things To Happen To SQL
Connor McDonald
 
実践 memcached
Masahiro Nagano
 
Demystifying cost based optimization
Riyaj Shamsudeen
 
Get your moneys worth out of your database
Patrick Barel
 
Oracle Database 12c Application Development
Saurabh K. Gupta
 
Extreme JavaScript Performance
Thomas Fuchs
 
Down the rabbit hole, profiling in Django
Remco Wendt
 
JPoint 2016 - Валеев Тагир - Странности Stream API
tvaleev
 
Using Optimizer Hints to Improve MySQL Query Performance
oysteing
 
Rich and Snappy Apps (No Scaling Required)
Thomas Fuchs
 

Similar to KScope19 - SQL Features (20)

PDF
ILOUG 2019 - SQL features for Developers
Connor McDonald
 
PPTX
SQL techniques for faster applications
Connor McDonald
 
DOC
ORACLE NOTES
Sachin Shukla
 
PPTX
Wellington APAC Groundbreakers tour - SQL Pattern Matching
Connor McDonald
 
DOCX
It6312 dbms lab-ex2
MNM Jain Engineering College
 
PDF
OOW19 - Ten Amazing SQL features
Connor McDonald
 
PPT
Oracle tips and tricks
Yanli Liu
 
PPTX
Analytic SQL Sep 2013
Connor McDonald
 
PPTX
Analytic functions in Oracle SQL - BIWA 2017
Connor McDonald
 
PPT
Sql query [select, sub] 4
Dr. C.V. Suresh Babu
 
DOC
SQLQueries
karunakar81987
 
PPTX
My SQL.pptx
KieveBarreto1
 
PDF
DBMS Notes selection projection aggregate
Sreedhar Chowdam
 
PPT
Sql 2006
Cathie101
 
PPTX
SQL
Bhandari Nawaraj
 
PPTX
SQL(NEW).pptx
PoojaChawan2
 
PPTX
Complex Queries using MYSQL00123211.pptx
metriohanzel
 
PDF
Oracle (SQL), Sulieman Khudruj
Sulieman Khudruj
 
PDF
Master SQL from Scratch_ Beginners to Advanced 📝.pdf
gobilgobil
 
ILOUG 2019 - SQL features for Developers
Connor McDonald
 
SQL techniques for faster applications
Connor McDonald
 
ORACLE NOTES
Sachin Shukla
 
Wellington APAC Groundbreakers tour - SQL Pattern Matching
Connor McDonald
 
It6312 dbms lab-ex2
MNM Jain Engineering College
 
OOW19 - Ten Amazing SQL features
Connor McDonald
 
Oracle tips and tricks
Yanli Liu
 
Analytic SQL Sep 2013
Connor McDonald
 
Analytic functions in Oracle SQL - BIWA 2017
Connor McDonald
 
Sql query [select, sub] 4
Dr. C.V. Suresh Babu
 
SQLQueries
karunakar81987
 
My SQL.pptx
KieveBarreto1
 
DBMS Notes selection projection aggregate
Sreedhar Chowdam
 
Sql 2006
Cathie101
 
SQL(NEW).pptx
PoojaChawan2
 
Complex Queries using MYSQL00123211.pptx
metriohanzel
 
Oracle (SQL), Sulieman Khudruj
Sulieman Khudruj
 
Master SQL from Scratch_ Beginners to Advanced 📝.pdf
gobilgobil
 
Ad

More from Connor McDonald (15)

PDF
APEX tour 2019 - successful development with autonomous
Connor McDonald
 
PDF
APAC Groundbreakers 2019 - Perth/Melbourne
Connor McDonald
 
PDF
OOW19 - Flashback, not just for DBAs
Connor McDonald
 
PDF
OOW19 - Read consistency
Connor McDonald
 
PDF
OOW19 - Slower and less secure applications
Connor McDonald
 
PDF
OOW19 - Killing database sessions
Connor McDonald
 
PDF
Latin America Tour 2019 - 18c and 19c featues
Connor McDonald
 
PDF
Latin America Tour 2019 - slow data and sql processing
Connor McDonald
 
PDF
OG Yatra - upgrading to the new 12c+ optimizer
Connor McDonald
 
PDF
OG Yatra - 25 years of hints and tips
Connor McDonald
 
PDF
OG Yatra - Flashback, not just for developers
Connor McDonald
 
PDF
Kscope19 - Flashback: Good for Developers as well as DBAs
Connor McDonald
 
PDF
Kscope19 - Understanding the basics of SQL processing
Connor McDonald
 
PDF
18c and 19c features for DBAs
Connor McDonald
 
PDF
APEX Connect 2019 - SQL Tuning 101
Connor McDonald
 
APEX tour 2019 - successful development with autonomous
Connor McDonald
 
APAC Groundbreakers 2019 - Perth/Melbourne
Connor McDonald
 
OOW19 - Flashback, not just for DBAs
Connor McDonald
 
OOW19 - Read consistency
Connor McDonald
 
OOW19 - Slower and less secure applications
Connor McDonald
 
OOW19 - Killing database sessions
Connor McDonald
 
Latin America Tour 2019 - 18c and 19c featues
Connor McDonald
 
Latin America Tour 2019 - slow data and sql processing
Connor McDonald
 
OG Yatra - upgrading to the new 12c+ optimizer
Connor McDonald
 
OG Yatra - 25 years of hints and tips
Connor McDonald
 
OG Yatra - Flashback, not just for developers
Connor McDonald
 
Kscope19 - Flashback: Good for Developers as well as DBAs
Connor McDonald
 
Kscope19 - Understanding the basics of SQL processing
Connor McDonald
 
18c and 19c features for DBAs
Connor McDonald
 
APEX Connect 2019 - SQL Tuning 101
Connor McDonald
 
Ad

Recently uploaded (20)

PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
PDF
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
PDF
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
PDF
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
PDF
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PPTX
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PDF
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PPTX
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PDF
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
What Makes Contify’s News API Stand Out: Key Features at a Glance
Contify
 
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
Achieving Consistent and Reliable AI Code Generation - Medusa AI
medusaaico
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
From Code to Challenge: Crafting Skill-Based Games That Engage and Reward
aiyshauae
 
Bitcoin for Millennials podcast with Bram, Power Laws of Bitcoin
Stephen Perrenod
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
Webinar: Introduction to LF Energy EVerest
DanBrown980551
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
POV_ Why Enterprises Need to Find Value in ZERO.pdf
darshakparmar
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
COMPARISON OF RASTER ANALYSIS TOOLS OF QGIS AND ARCGIS
Sharanya Sarkar
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 

KScope19 - SQL Features

  • 2. Copyright Š 2017, Oracle and/or its affiliates. All rights reserved. SQLThe meanest, fastest thing out there Connor McDonald 2
  • 3. Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. Connor McDonald
  • 4. Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. | 4
  • 5. Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. | 5
  • 6. Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. | Stuff 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 rants and raves on tech and the world :-)
  • 7. 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
  • 8. Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. |Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. | https://asktom.oracle.com
  • 9. 9
  • 10. SO
  • 11. THE
  • 12. BIG
  • 14. IS
  • 16. why talk about SQL ? 16
  • 18. 18
  • 19. why talk about SQL # 1 19
  • 21. 21
  • 22. why talk about SQL # 2 22
  • 26. 26 "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'
  • 29. SQL is entirely APIs ! 29
  • 30. 30 "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;
  • 31. why talk about SQL # 3 31
  • 34. ... yet we end up data processing :-( 34
  • 35. 35
  • 37. this session is not about ... 37
  • 39. we can do anything ... 39
  • 40. 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) 40
  • 41. 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 ) 41 Ack: Anton Scheffer, https://technology.amis.nl
  • 42. 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; 42 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
  • 44. 44 100% % of developers that will need to solve Sudoku as part of their job
  • 45. 45 100% % of developers that need to get real stuff done
  • 47. 47 1
  • 53. DBA friendship is important 53 oc00.sql
  • 54. 54 2
  • 56. "Employee salary list, plus department total, plus grand total" 56
  • 57. 57
  • 58. 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 58 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
  • 59. from 3 to 2 59 rollup
  • 60. 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 60 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
  • 62. EMPNO SAL DEPTNO ---------- ---------- ---------- 7782 2450 10 7839 5000 10 7934 1300 10 7566 2975 20 7902 3000 20 7876 1100 20 7369 800 20 62 DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 9400 29025 7782 2450 10 7839 5000 10 7934 1300 10 7566 2975 20 10 8750
  • 63. from 2 to 1 63
  • 64. 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 2902564
  • 65. all totals are possible 65
  • 66. 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 66
  • 68. 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 68
  • 69. 69 3
  • 71. C#, C++ ESB Tuxedo Weblogic Stored Procedure 71
  • 72. 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; } }72
  • 74. 74
  • 77. SQL can be complex 77
  • 78. SQL should "self document" 78
  • 79. query blocks = self documenting SQL 79
  • 80. 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 80
  • 81. 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 | 81
  • 82. ? 82 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 |
  • 83. 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 83 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
  • 84. 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 84
  • 85. 85 4
  • 87. SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_GREAT_FAT_TABLE; 87 MY_HUGE_GREAT_FAT_TABLE;
  • 88. 88
  • 89. 89
  • 90. 90
  • 91. 91
  • 92. 92
  • 93. SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_GREAT_FAT_TABLE; Elapsed: 06:12:34.00 93
  • 94. SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_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 94
  • 95. 95
  • 96. 96
  • 97. 97 and then we do this :-)
  • 98. SQL> select count(*) from MY_TABLE; COUNT(*) ---------- 0 98
  • 101. skip / bypass bad rows 101
  • 103. SQL> insert into MY_TABLE 2 select * 3 from MY_HUGE_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" 103
  • 106. DBMS_ERRLOG.CREATE_ERROR_LOG ( dml_table_name IN VARCHAR2, err_log_table_name IN VARCHAR2 := NULL, err_log_table_owner IN VARCHAR2 := NULL, ... 106
  • 107. 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) 107
  • 108. 108
  • 110. add to EMP from NEW_DATA 110
  • 111. SQL> select * from NEW_DATA; EMPNO SAL DEPTNO ---------- ---------- ---------- 1000 5000 20 100X 3550 10 2000 2500 50 7934 4000 20 111 non-numeric no dept 50 duplicate
  • 112. 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. 112 50
  • 113. 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 113
  • 114. 114 5
  • 116. 116 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
  • 118. 118 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 118
  • 119. bookings by hour per room 119
  • 120. 120 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
  • 121. 121 SQL> select * 2 from timeslots; HR -- 8 9 10 11 12 13 14 15 16 x "Room 1" x "Room 2" ... x "Room n"
  • 123. 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 123
  • 124. 124 6
  • 128. 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 128
  • 129. "who cares?....... more code, same result" 129
  • 130. WITH last_hire AS ( select deptno, max(hiredate) from emp group by deptno ) select * from last_hire; 130
  • 131. why is it cool ? 131
  • 133. relational is a rigorous model ... 133
  • 134. relational is the dominant model ... 134
  • 135. relational ... can sortta suck 135
  • 138. "data is represented as mathematical n-ary relations, an n-ary relation being a subset of the Cartesian product of n domains." 138
  • 139. 139
  • 142. "First, get the total salary paid by each department, then get the average of these totals, then list those departments above that average" 142 SQL ?
  • 143. "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), 143
  • 144. "...then get the average of these totals... 6 avg_sal AS ( SELECT AVG(dept_sal) avsal 7 FROM dept_salaries) 144
  • 145. "...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; 145
  • 146. 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; 146
  • 152. 152 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"}]
  • 153. 153 7
  • 155. 155 "employees by hiredate, recent first"
  • 156. 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 156
  • 158. 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 158
  • 159. 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; 159
  • 160. 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 160
  • 161. 161 "TL;DR ... my app can do it"
  • 162. 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(); } 162
  • 165. let the database know 165
  • 166. SQL> select * 2 from ( 3 select empno, ename, hiredate 4 from emp 5 order by hiredate desc 6 ) 7 where rownum <= 5; 166 ------------------------------------------------ | 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 | ------------------------------------------------
  • 167. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc 4 fetch first 5 rows only; 167 ------------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | |* 2 | WINDOW SORT PUSHED RANK| | 14 | | 3 | TABLE ACCESS FULL | EMP | 14 | -------------------------------------------------
  • 168. you get other benefits 168 oc02.sql
  • 169. 169 "but what about the next page ?"
  • 172. 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 172
  • 173. forget the OFFSET clause 173
  • 174. 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 174 fetch first 5 rows offset 5 fetch next ... 17-FEB-91 7521 BROWN
  • 175. 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 175 17-FEB-91 7521 BROWN SQL> select empno, ename, hiredate 2 from emp 3 where hiredate < :last_shown 3 order by hiredate desc;
  • 176. 176 "an expensive query per page ?!?!
  • 178. 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 178 /*+ result_cache */ rownum r, f.* oc03.sql r between 11 and 20
  • 179. 179 8
  • 180. we all know about analytics 180
  • 181. SQL> select row_number() OVER ( order by sal ) 2 from emp 3 ... 181 https://bit.ly/analytic_sql
  • 182. 182 “Show me lowest salary for each department...” SQL> select deptno, min(sal) 2 from emp 3 group by deptno; “...and I need to know who has that lowest salary as well” SQL> select deptno, empno, min(sal) 2 from emp 3 group by deptno; ORA-00979: not a GROUP BY expression
  • 184. SQL> select deptno, min(sal), min(empno) 2 KEEP ( dense_rank FIRST order by sal) empno 3 from emp 4 group by deptno 5 / DEPTNO MIN(SAL) EMPNO ---------- ---------- ---------- 10 1300 7934 20 800 7369 30 950 7900 Emp 7934 has the lowest salary in dept 10 184
  • 187. 187
  • 188. 188
  • 189. 189
  • 191. "Find 10 consecutive deposits in a 24 hour period, then a withdrawal within three days of the last deposit, at a different retail outlet" 191
  • 192. ACCT TSTAMP TYP AMT LOC ---------- ------------------ ---------- ------- ---- 54261 25/01/19 17:20:55 Deposit 100 Perth 54261 25/01/19 17:56:58 Deposit 165 Perth 54261 26/01/19 11:24:14 Deposit 30 Subiaco 54261 26/01/19 11:47:53 Deposit 45 Guildford 54261 26/01/19 12:59:38 Deposit 100 Claremont 54261 26/01/19 13:26:04 Deposit 80 Perth 54261 26/01/19 14:41:09 Deposit 50 Perth 54261 26/01/19 14:53:12 Deposit 50 Nedlands 54261 26/01/19 15:15:05 Deposit 50 Leederville 54261 26/01/19 15:51:17 Deposit 50 Guildford 54261 26/01/19 16:15:02 Deposit 120 Perth 54261 26/01/19 16:36:51 Deposit 100 Perth 54261 26/01/19 16:55:09 Deposit 100 Perth 54261 26/01/19 18:07:17 Withdrawal -500 Nedlands 192
  • 195. 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 = 'Deposit', 14 wthd as 15 txn_type = 'Withdrawal' 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 ) 195
  • 198. 198
  • 199. 199 "talking" to your database ... makes it faster
  • 202. 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 202 hash outer join ? nested loop ? STORES first ? sort merge ?
  • 203. --------------------------------------------------- | 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 | --------------------------------------------------- 203
  • 204. 204 can we do better ? add indexes ? rewrite query ? result cache ? materialized view ?
  • 205. 205 share your knowledge with the db oc04.sql
  • 211. never too early to start 211
  • 213. Copyright Š 2018, Oracle and/or its affiliates. All rights reserved. | That's a wrap! youtube bit.ly/youtube-connor blog bit.ly/blog-connor twitter bit.ly/twitter-connor