SlideShare ist ein Scribd-Unternehmen logo
1 von 265
WE
ARE
SHOWING
CODING SAMPLES
SO IF YOU HAVE PASSED
THE AGE OF TWENTY THEN YOU SHOULD PROBABLY THINK
ABOUT SITTING RIGHT UP CLOSE TO THE FRONT OF THE ROOM BECAUSE OTHERWISE YOU MIGHT MISS OUT
A N D I F Y O U C A N R E A D T H I S, T H E N Y O U S H O U L D L E A V E B E C A U S E Y O U H A V E S U P E R P O W E R S A N D Y O U S H O U L D B E I N A N A V E N G E R S M O V I E N O T L E A R N I N G A B O U T I N F O R M A T I O N T E C H N O L O G Y. :-)
2
Connor McDonald
4
5
6
@connor_mc_d connormcdonald.wordpress.com
7
https://www.youtube.com/c/ConnorMcDonaldOracle
https://www.facebook.com/connor.mcdonald42
8
asktom.oracle.com
why talk about SQL
9
# 1
after all ...
10
11
NoSQL
12
non relational
13
why talk about SQL
14
# 2
developers
15
get
16
stuff donehard
coding for functionality ...
17
... not for data processing
18
a little bit of SQL ...
19
... can make your apps awesome
20
key point
21
this session is about ...
22
smart not smart-ass
23
SQL can do anything ...
24
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)
25
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 )
26
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;
27
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
-----------
28
sud.sql
29
100%
% of developers that
will need to solve Sudoku
as part of their job
30
100%
% of developers that need
to get real stuff done
real stuff
31
32
1
some controversy...
33
34
DBA
36Public
37Public
DBA stuff matters
38
oc00.sql
39
2
synthesizing rows
40
"What if I don't have a TAB200K ?"
41
insert into my_transactions1
select ...
from tab200k;
the problem ...
42
databases store data
43
only just enough
44
SQL> select * from meetings;
SCHEDULED OWNER
--------- -------------------------
06-MAY-17 Connor
13-MAY-17 Gerald
17-MAY-17 Maria
45
Connor
Gerald
Maria
free free free free free free
free free free free free free
free free free free free
free free free
free free freefree free free
freefree
what we need
46
47
SQL> select * from meetings;
SCHEDULED OWNER
--------- -----------------------
01-MAY-17
02-MAY-17
03-MAY-17
04-MAY-17
05-MAY-17
06-MAY-17 Connor
07-MAY-17
08-MAY-17
...
16-MAY-17
17-MAY-17 Maria
18-MAY-17
19-MAY-17
...
30-MAY-17
31-MAY-17
31 ? 365 ?
48
any number of rows
49
easy
50
SQL> select level seq
2 from DUAL
3 connect by level <= 10;
SEQ
----------
1
2
3
4
5
6
7
8
9
10
10 rows selected.
51
Oracle
select *
from generate_series(1, 10)
52
with gen(seq) as (
select 1 seq
union all
select seq+1 from gen
where seq < 10
)
select * from gen;
select seq
from my_n_row_table
Postgres
SQL Server
MySQL
SQL> select level seq
2 from DUAL
3 connect by level <= 10;
-----------------------------------------------------
| Id | Operation | Name | Rows |
-----------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
|* 1 | CONNECT BY WITHOUT FILTERING| | |
| 2 | FAST DUAL | | 1 |
-----------------------------------------------------
Statistics
------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
53
"free"
54
if I have integers ...
55
... I have dates
56
SQL> select date '2017-04-30'+level dte
2 from dual
3 connect by level <= 31;
DTE
---------
01-MAY-17
02-MAY-17
03-MAY-17
04-MAY-17
...
...
29-MAY-17
30-MAY-17
31-MAY-17
31 rows selected.
57
outer join
58
59
SQL> select
2 dte scheduled,
3 m.owner
4 from
5 ( select date '2017-04-30'+level dte
6 from dual
7 connect by level <= 31 ) d
8 left outer join
9 meetings m
10 on d.dte = m.scheduled
11 order by 1;
SCHEDULED OWNER
--------- -----------------------
01-MAY-17
02-MAY-17
03-MAY-17
04-MAY-17
05-MAY-17
06-MAY-17 Connor
07-MAY-17
08-MAY-17
...
16-MAY-17
17-MAY-17 Maria
18-MAY-17
19-MAY-17
...
30-MAY-17
31-MAY-17
60
3
subquery factoring
61
common table expressions
62
WITH clause
63
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
64
"gee....... more code, same result"
65
WITH last_hire AS
(
select deptno, max(hiredate)
from emp
group by deptno
)
select * from last_hire;
66
why is it cool ?
67
good solution metaphor
68
relational is a rigorous model ...
69
relational is dominant ...
70
relational ... can sortta suck :-)
71
not our fault
72
Codd & Date
73
"data is represented as mathematical n-ary
relations, an n-ary relation being a subset of the
Cartesian product of n domains."
74
huh ?
75
procedural, linear world
76
"First, get the total salary paid by each department,
then get the average of these totals,
then list those departments above that average"
77
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),
78
"...then get the average of these totals...
6 avg_sal AS ( SELECT AVG(dept_sal) avsal
7 FROM dept_salaries)
79
"...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;
80
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;
81
programmer's approach....
82
... relational solution
83
the "finishing touches"
84
recall : 31 days of meetings
85
86
SQL> with raw_data as (
2 select
3 dte scheduled,
4 m.owner
5 from
6 ( select date '2017-04-30'+level dte
7 from dual
8 connect by level <= 31 ) d
9 left outer join
10 meetings m
11 on d.dte = m.scheduled
12 )
13 select
14 json_arrayagg(
15 json_object(key to_char(scheduled) value owner )
16 order by scheduled ) as meetings
17 from raw_data ;
[{"01-MAY-17":null},
{"02-MAY-17":null},
{"03-MAY-17":null},
{"04-MAY-17":null},
{"05-MAY-17":null},
{"06-MAY-17":"Connor"},
{"07-MAY-17":null},
{"08-MAY-17":null},
{"09-MAY-17":null},
{"10-MAY-17":null},
...
...
...
{"30-MAY-17":null},
{"31-MAY-17":null}
]
execution plan
87
two possibilities
88
temporary storage
89
90
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;
join
----------------------------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TEMP TABLE TRANSFORMATION | |
| 2 | LOAD AS SELECT | |
| 3 | HASH GROUP BY | |
| 4 | MERGE JOIN | |
| 5 | TABLE ACCESS BY INDEX ROWID| DEPT |
| 6 | INDEX FULL SCAN | PK_DEPT |
| 7 | SORT JOIN | |
| 8 | TABLE ACCESS FULL | EMP |
| 9 | SORT ORDER BY | |
| 10 | NESTED LOOPS | |
| 11 | VIEW | |
| 12 | SORT AGGREGATE | |
| 13 | VIEW | |
| 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6624_AF422F5 |
| 15 | VIEW | |
| 16 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6624_AF422F5 |
----------------------------------------------------------------------
91
SQL> alter session set sql_trace = true;
Session altered.
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) asal
7 FROM dept_salaries)
8 SELECT * FROM dept_salaries d, avg_sal a
9 WHERE d.dept_sal > a.asal
10 ORDER BY d.dname;
DNAME DEPT_SAL ASAL
-------------- ---------- ----------
RESEARCH 21750 19350
SQL> alter session set sql_trace = false;
Session altered.
92
PARSING IN CURSOR #12 len=179 dep=1 uid=0 oct=1...
CREATE GLOBAL TEMPORARY
TABLE "SYS"."SYS_TEMP_0FD9D6625_AF422F5"
("C0" VARCHAR2(14),"C1" NUMBER )
IN_MEMORY_METADATA CURSOR_SPECIFIC_SEGMENT
STORAGE (OBJNO 4254950949 ) NOPARALLEL
END OF STMT
93
no temporary storage
94
------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | NESTED LOOPS | |
| 3 | VIEW | |
| 4 | SORT AGGREGATE | |
| 5 | VIEW | |
| 6 | HASH GROUP BY | |
| 7 | MERGE JOIN | |
| 8 | TABLE ACCESS BY INDEX ROWID| DEPT |
| 9 | INDEX FULL SCAN | PK_DEPT |
| 10 | SORT JOIN | |
| 11 | TABLE ACCESS FULL | EMP |
| 12 | VIEW | |
| 13 | SORT GROUP BY | |
| 14 | MERGE JOIN | |
| 15 | TABLE ACCESS BY INDEX ROWID | DEPT |
| 16 | INDEX FULL SCAN | PK_DEPT |
| 17 | SORT JOIN | |
| 18 | TABLE ACCESS FULL | EMP |
------------------------------------------------------
95
96
4
partitioned outer join
97
98
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
99
conventional outer join
100
SQL> SELECT hrs.hr, t1.room, t1.who
2 from timeslots hrs
3 left outer join bookings t1
4 on hrs.hr = t1.hr
HR ROOM WHO
------- ---------- ----------
8 Room2 PETE
9 Room1 JOHN
10
11 Room1 MIKE
12
13
14 Room2 JILL
15 Room2 JANE
16 Room1 SAM
100
bookings by hour per room
101
102
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
103
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
104
105
SQL> SELECT hrs.hr, t1.room, t1.who
2 FROM bookings t1
3 PARTITION BY (t1.room)
4 RIGHT OUTER JOIN hrs ON (hrs.hr = t1.hr);
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
105
106
5
pagination
107
108
"employees by hiredate, recent first"
SQL> select empno, ename, hiredate
2 from emp
3 limit 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
109
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
110
inline view
111
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
112
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;
113
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
114
115
"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();
}
116
118
demo
119
oc01.sql
let the database know
120
SQL> select *
2 from (
3 select empno, ename, hiredate
4 from emp
5 order by hiredate desc
6 )
7 where rownum <= 5;
121
------------------------------------------------
| 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;
122
-------------------------------------------------
| 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
123
oc02.sql
124
"but what about the next page ?"
there
125
is
no
next
page
new query
126
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
127
128
"an expensive query per page ?!?!
consider result caching
129
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
130
/*+ result_cache */ rownum r, f.*
oc03.sql
r between 11 and 20
131
6
query block naming
132
C#, C++ ESB Tuxedo
Weblogic
Stored
Procedure
133
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;134
no comments
135
136
"C# is self-documenting"
137
"uh huh"
138
SQL can be complex
139
SQL should "self document"
140
query blocks =
self-documenting SQL
141
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
142
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 |
143
?
144
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
145
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
146
assist with query trace
147
SQL> alter session set
2 events = '10053 trace name context forever, level 1';
Session altered.
148
**************************
Query transformations (QT)
**************************
CBQT: Validity checks passed for 7jpzpr2475cqw.
CSE: Sub-expression elimination in query block SEL$1 (#0)
*************************
Common Subexpression elimination (CSE)
*************************
CSE: CSE not performed on query block YR_HIRE (#0).
CSE: Sub-expression elimination in query block AV_SAL (#0)
CSE: CSE not performed on query block AV_SAL (#0).
CSE: CSE not performed on query block SEL$1 (#0).
***************************
Order-by elimination (OBYE)
***************************
OBYE: Considering Order-by Elimination from view SEL$1 (#0)
149
*********************************
Number of join permutations tried: 1
*********************************
GROUP BY adjustment factor: 1.000000
GROUP BY cardinality: 3.000000, TABLE cardinality: 14.000000
SORT ressource Sort statistics
Sort width: 598 Area size: 1048576 Max Area: 104857600
Degree: 1
Blocks to Sort: 1 Row size: 18 Total Rows: 14
Initial runs: 1 Merge passes: 0 IO Cost / pass: 0
Total IO sort cost: 0 Total CPU sort cost: 14312402
Total Temp space used: 0
Trying or-Expansion on query block AV_SAL (#3)
Transfer Optimizer annotations for query block AV_SAL (#3)
GROUP BY adjustment factor: 1.000000
Final cost for query block AV_SAL (#3) - All Rows Plan:
Best join order: 1
Cost: 4.0029 Degree: 1 Card: 14.0000 Bytes: 98
Resc: 4.0029 Resc_io: 3.0000 Resc_cpu: 14352069
Resp: 4.0029 Resp_io: 3.0000 Resc_cpu: 14352069
150
footnote
151
152
select
/*+ QB_NAME(top)
INDEX(@yr_hire emp (empno))
FULL(@av_sal emp)
*/
INDEX(emp emp_ix)
153
7
totals / subtotals
154
"Employee salary list,
plus department total,
plus grand total"
155
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
156
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
157
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
158
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...
159
EMPNO SAL DEPTNO
---------- ---------- ----------
7782 2450 10
7839 5000 10
7934 1300 10
7566 2975 20
7902 3000 20
7876 1100 20
7369 800 20
160
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
161
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
29025162
the whole lot !
163
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
164
totally customisable
165
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
166
167
8
pattern matching
168
169
170
171
AML
172
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"
173
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
174
hard...
175
pattern matching
176
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 )
177
178
9
179
180
"talking" to your database
... makes it faster
181
example
182
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
183
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 |
---------------------------------------------------
184
185
can we do better ?
add indexes ?
rewrite query ?
result cache ?
materialized view ?
186
share your knowledge with the db
oc04.sql
187
10
transposition
188
rows to columns, colums to rows
189
"I need sales by product
for each quarter....now"
190
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
...
191
"That’s wrong!...surely you know
I wanted it ACROSS the page"
192
193
194
pivot clause
195
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
196
or ...
197
"That’s wrong!...surely you know
I wanted it DOWN the page"
198
SQL> desc SALES_ACROSS
Name Null? Type
----------------------------- -------- -------------
PRODUCT VARCHAR2(20)
Q1 NUMBER
Q2 NUMBER
Q3 NUMBER
Q4 NUMBER
199
unpivot clause
200
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"
201
elements must be known in advance
202
203
11
scalar queries
204
SQL> select
2 ( select dname
3 from dept
4 where deptno = e.deptno ) dname,
5 decode(empno, 7499,
6 ( select max(sal) from emp ),
7 -1)
8 from
9 ( select * from emp
10 where sal > 0 ) e
11 where
12 ( select max(hiredate) from emp ) < sysdate
13 /
scalar
anywhere an
expression could be
205
"big deal"
206
SQL> create or replace
2 function CALC_TAX(p int) return number is
3 begin
4 dbms_lock.sleep(1);
5 return p;
6 end;
7 /
Function created.
SQL> create table T
2 as select rownum r, mod(rownum,5) r1 from dual
3 connect by level <= 30;
Table created.
1,2,3,..., 30
0,1,2,3,4,0,1,2,3,4, ...
207
SQL> select r, calc_tax(r1) tax from T;
R TAX
---------- ----------
1 1
2 2
3 3
4 4
...
28 3
29 4
30 0
30 rows selected.
Elapsed: 00:00:30.01
208
SQL> select r,
2 ( select calc_tax(r1) from dual) as tax
3 from T;
R TAX
---------- ----------
1 1
2 2
...
28 3
29 4
30 0
30 rows selected.
Elapsed: 00:00:05.01
209
subquery caching
... any subquery
210
what about multiple values
211
SQL> select
2 empno,
3 ( select dname, loc, revenue
4 from dept
5 where deptno = e.deptno )
6 from EMP e;
( select dname, loc, revenue
*
ERROR at line 3:
ORA-00913: too many values
212
SQL> select
2 empno,
3 ( select dname
4 from dept
5 where deptno = e.deptno ) dname,
6 ( select loc
7 from dept
8 where deptno = e.deptno ) loc,
9 ( select revenue
10 from dept
11 where deptno = e.deptno ) rev
12 from EMP e;
EMPNO DNAME LOC REV
---------- -------------- ------------- ----------
7839 ACCOUNTING NEW YORK 10000
7698 SALES CHICAGO 30000
7782 ACCOUNTING NEW YORK 10000
...
213
use a type
214
SQL> create type multi_attrib as object (
2 dname varchar2(10),
3 loc varchar2(10),
4 rev number );
5 /
Type created.
215
SQL> select empno,
2 x.attr.dname,
3 x.attr.loc,
4 x.attr.rev
5 from
6 (
7 select
8 empno,
9 ( select multi_attrib(dname,loc,revenue)
10 from dept
11 where deptno = e.deptno ) attr
12 from EMP e
13 ) x;
EMPNO ATTR.DNAME ATTR.LOC ATTR.REV
---------- ---------- ---------- ----------
7839 ACCOUNTING NEW YORK 10000
7698 SALES CHICAGO 30000
7782 ACCOUNTING NEW YORK 10000
216
217
12
first principles
218
219
SQL> select rpad(' ',level)||ename,
2 from emp
3 start with mgr is null
4 connect by prior empno = mgr
ENAME
---------------------------
KING
BLAKE
JAMES
ALLEN
WARD
CLARK
MILLER
220
SQL> select empno, ename, mgr
2 from emp
3 where mgr is null;
EMPNO ENAME MGR
---------- -------------------- ----------
7839 KING
221
SQL> select e2.empno, e2.ename, e2.mgr
2 from emp e2,
3 ( select empno, mgr
4 from emp
5 where mgr is null ) inner
6 where e2.mgr = inner.empno;
EMPNO ENAME MGR
---------- -------------------- ----------
7566 JONES 7839
7698 BLAKE 7839
7782 CLARK 7839
222
SQL> select e3.empno, e3.ename, e3.mgr
2 from emp e3,
3 ( select e2.empno, e2.ename, e2.mgr
4 from emp e2,
5 ( select empno, mgr
6 from emp
7 where mgr is null ) inner
8 where e2.mgr = inner.empno ) inner
9 where e3.mgr = inner.empno;
EMPNO ENAME MGR
---------- -------------------- ----------
7902 FORD 7566
7788 SCOTT 7566
7900 JAMES 7698
7844 TURNER 7698
7654 MARTIN 7698
7521 WARD 7698
7934 MILLER 7782
223
SQL> select e4.empno, e4.ename, e4.mgr
2 from emp e4,
3 ( select e3.empno, e3.ename, e3.mgr
4 from emp e3,
5 ( select e2.empno, e2.ename, e2.mgr
6 from emp e2,
7 ( select empno, mgr
8 from emp
9 where mgr is null ) inner
10 where e2.mgr = inner.empno ) inner
11 where e3.mgr = inner.empno ) inner
12 where e4.mgr = inner.empno;
EMPNO ENAME MGR
---------- -------------------- ----------
7876 ADAMS 7788
recursive...
224
recall: WITH
225
WITH can be recursive
226
SQL> with EACH_LEVEL (empno, name, mgr) as
2 ( --
3 -- start with
4 --
5 select empno, ename, mgr
6 from emp
7 where mgr is null
8 --
9 -- connect by
10 --
11 union all
12 select emp.empno, emp.ename, emp.mgr
13 from emp, EACH_LEVEL
14 where emp.mgr = each_level.empno
15 )
16 select *
17 from each_level;
227
EMPNO NAME MGR
---------- --------------- ----------
7839 KING
7566 JONES 7839
7698 BLAKE 7839
7782 CLARK 7839
7499 ALLEN 7698
7521 WARD 7698
7654 MARTIN 7698
7788 SCOTT 7566
7844 TURNER 7698
7900 JAMES 7698
7902 FORD 7566
7934 MILLER 7782
7369 SMITH 7902
7876 ADAMS 7788
228
two part structure
229
with RECURSIVE_WITH (c1,c2,c3) as
(
<starting/entry point>
union all
<recursive relationship>
)
select ...
from RECURSIVE_WITH
230
you control pseudo-functions
231
SQL> with each_level (empno, name, mgr, rlevel) as
2 ( select empno, ename, mgr, 1 rlevel
3 from emp
4 where mgr is null
5 union all
6 select emp.empno, emp.ename, emp.mgr, rlevel+1
7 from emp, each_level
8 where emp.mgr = each_level.empno
9 )
10 select * from each_level;
EMPNO NAME MGR RLEVEL
---------- --------------- ---------- ----------
7839 KING 1
7566 JONES 7839 2
7698 BLAKE 7839 2
7782 CLARK 7839 2
7499 ALLEN 7698 3
...
232
SQL> with each_level (empno, name) as
2 ( select empno, ename from emp
3 where mgr is null
4 union all
5 select e.empno,
6 each_level.name||'-'||e.ename
7 from emp e, each_level
8 where e.mgr = each_level.empno
9 )
10 select empno, name from each_level;
EMPNO NAME
---------- --------------------------------
7839 KING
7566 KING-JONES
7698 KING-BLAKE
7782 KING-CLARK
7499 KING-BLAKE-ALLEN
7521 KING-BLAKE-WARD
...233
cycle detection
234
SQL> with each_level (empno, name, mgr) as
2 ( select empno, ename, mgr
3 from emp
4 where ename = 'KING'
5 union all
6 select emp.empno, emp.ename, emp.mgr
7 from emp, each_level
8 where emp.mgr = each_level.empno
9 )
10 select *
11 from each_level;
ERROR:
ORA-32044: cycle detected while executing recursive WITH query
235
SQL> with each_level (empno, name, mgr) as
2 ( select empno, ename, mgr from emp
3 where ename = 'KING'
4 union all
5 select emp.empno, emp.ename, emp.mgr
6 from emp, each_level
7 where emp.mgr = each_level.empno )
8 CYCLE mgr SET is_cycle TO 'Y' DEFAULT 'N'
9 select * from each_level;
EMPNO NAME MGR IS_CYCLE
---------- ---------- ---------- ----------
7839 KING 7499 N
7566 JONES 7839 N
7521 WARD 7698 N
7839 KING 7499 Y
7876 ADAMS 7788 N
...
236
traversal
237
SQL> with each_level (empno, name, hiredate, mgr) as
2 ( select empno, ename, hiredate, mgr from emp
3 where ename = 'KING'
4 union all
5 select e.empno,
6 each_level.name||'-'||e.ename, e.hiredate, e.mgr
7 from emp e, each_level
8 where e.mgr = each_level.empno )
9 SEARCH BREADTH FIRST BY HIREDATE SET IDX
10 select name, hiredate, idx from each_level;
NAME HIREDATE IDX
-------------------------------- --------- ----------
KING 17-NOV-81 1
KING-JONES 02-APR-81 2
KING-BLAKE 01-MAY-81 3
KING-CLARK 09-JUN-81 4
KING-BLAKE-ALLEN 20-FEB-81 5
KING-BLAKE-WARD 22-FEB-81 6
...
KING-JONES-FORD-SMITH 17-DEC-80 13
KING-JONES-SCOTT-ADAMS 23-MAY-87 14
238
SQL> with each_level (empno, name, hiredate, mgr) as
2 ( select empno, ename, hiredate, mgr from emp
3 where ename = 'KING'
4 union all
5 select e.empno,
6 each_level.name||'-'||e.ename, e.hiredate, e.mgr
7 from emp e, each_level
8 where e.mgr = each_level.empno )
9 SEARCH DEPTH FIRST BY HIREDATE SET IDX
10 select name, hiredate, idx from each_level;
NAME HIREDATE IDX
-------------------------------- --------- ----------
KING 17-NOV-81 1
KING-JONES 02-APR-81 2
KING-JONES-FORD 03-DEC-81 3
KING-JONES-FORD-SMITH 17-DEC-80 4
KING-JONES-SCOTT 19-APR-87 5
KING-JONES-SCOTT-ADAMS 23-MAY-87 6
KING-BLAKE 01-MAY-81 7
KING-BLAKE-ALLEN 20-FEB-81 8
etc
239
240
iteration / nesting
241
SQL> select * from messages;
TXT
----------------------------------------------------------
I caught up with Connor and Maria Colgan today. They have
taken over AskTOM for Oracle Developers
242
SQL> select * from twitter_handles;
ID TERM HANDLE
---- ------------------------------ ---------------
1 Connor McDonald @connor_mc_d
2 Connor @connor_mc_d
3 Maria Colgan @sqlmaria
4 Oracle Developers @otndev
5 Oracle @oracle
6 AskTOM @oracleasktom
243
SQL> with
2 tweetised(ind,tweet_txt) as
3 (
4 select 1 ind, txt tweet_txt
5 from messages
6 union all
7 select ind+1, replace(tweet_txt,term,handle)
8 from tweetised, twitter_handles
9 where ind = id
10 )
11 select * from tweetised;
244
IND TWEET_TXT
--------- -----------------------------------------------------------------------------------------
1 I caught up with Connor and Maria Colgan today. They have taken over AskTOM for...
2 I caught up with Connor and Maria Colgan today. They have taken over AskTOM for...
3 I caught up with @connor_mc_d and Maria Colgan today. They have taken over AskTOM for...
4 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for ...
5 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for @otndev
6 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for @otndev
7 I caught up with @connor_mc_d and @sqlmaria today. They have taken over @oracleasktom ...
245
SQL> with
2 tweetised(ind,tweet_txt) as
3 (
4 select 1 ind, txt tweet_txt
5 from messages
6 union all
7 select ind+1, replace(tweet_txt,term,handle)
8 from tweetised, twitter_handles
9 where ind = id
10 )
11 select * from tweetised
12 order by ind desc
13 fetch first 1 row only;
IND TWEET_TXT
---------- ------------------------------------------------------
7 I caught up with @connor_mc_d and @sqlmaria today. They...
246
247
last
staying up to date
248
249
250
"fill in the blanks"
251
SQL> select dt, val
2 from t
3 order by dt;
DT VAL
--------- ----------
02-JAN-11 195
03-JAN-11
04-JAN-11
05-JAN-11
06-JAN-11 129
07-JAN-11
08-JAN-11
09-JAN-11
10-JAN-11 87
11-JAN-11
...
195
195
195
129
129
129
87
252
SQL> select dt, val,
2 case when val is not null
3 then to_char(row_number() over (order by dt),'fm0000')||'-'||val
4 end max_val
5 from t
6 order by dt;
DT VAL MAX_VAL
--------- ---------- -----------
02-JAN-11 195 0001-195
03-JAN-11
04-JAN-11
05-JAN-11
06-JAN-11 129 0005-129
07-JAN-11
08-JAN-11
09-JAN-11
10-JAN-11 87 0009-87
11-JAN-11
...
253
SQL> select dt, val,
2 max(max_val) over (order by dt) max_val_str
3 from ( select dt, val,
4 case when val is not null
5 then to_char(row_number() over (order by dt),'fm0000')||'-'||val
6 end max_val
7 from t ) order by dt;
DT VAL MAX_VAL_STR
--------- ---------- ------------------
02-JAN-11 195 0001-195
03-JAN-11 0001-195
04-JAN-11 0001-195
05-JAN-11 0001-195
06-JAN-11 129 0005-129
07-JAN-11 0005-129
08-JAN-11 0005-129
09-JAN-11 0005-129
10-JAN-11 87 0009-87
11-JAN-11 0009-87
...
254
SQL> select dt, val,
2 to_number(substr(max(max_val) over (order by dt),5)) max_val
3 from ( select dt, val,
4 case when val is not null
5 then to_char(row_number() over (order by dt),'fm0000')||val
6 end max_val
7 from t ) order by dt
8 /
DT VAL MAX_VAL
--------- ---------- ----------
02-JAN-11 195 195
03-JAN-11 195
04-JAN-11 195
05-JAN-11 195
06-JAN-11 129 129
07-JAN-11 129
08-JAN-11 129
09-JAN-11 129
10-JAN-11 87 87
11-JAN-11 87
255
SQL> select dt, val,
2 last_value(val ignore nulls) over (order by dt) val
3 from t
4 order by dt;
DT VAL VAL
--------- ---------- ----------
02-JAN-11 195 195
03-JAN-11 195
04-JAN-11 195
05-JAN-11 195
06-JAN-11 129 129
07-JAN-11 129
08-JAN-11 129
09-JAN-11 129
10-JAN-11 87 87
11-JAN-11 87
wrap up
256
SQL
257
very cool
258
very powerful
259
defacto language polyglot world
260
less code
261
never too early to start
262
SQL>
Connected.
SQL>
ORACLE instance shut down.
SQL>
conn / as sysdba
shutdown abort
@connor_mc_d
#MakeSQLGreatAgain
@connor_mc_d

Weitere ähnliche Inhalte

Was ist angesagt?

SQL WORKSHOP::Lecture 4
SQL WORKSHOP::Lecture 4SQL WORKSHOP::Lecture 4
SQL WORKSHOP::Lecture 4
Umair Amjad
 

Was ist angesagt? (20)

Sangam 2019 - The Latest Features
Sangam 2019 - The Latest FeaturesSangam 2019 - The Latest Features
Sangam 2019 - The Latest Features
 
KScope19 - SQL Features
KScope19 - SQL FeaturesKScope19 - SQL Features
KScope19 - SQL Features
 
Sangam 18 - Great Applications with Great SQL
Sangam 18 - Great Applications with Great SQLSangam 18 - Great Applications with Great SQL
Sangam 18 - Great Applications with Great SQL
 
APEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQLAPEX Connect 2019 - array/bulk processing in PLSQL
APEX Connect 2019 - array/bulk processing in PLSQL
 
SQL Tuning 101 - Sep 2013
SQL Tuning 101 - Sep 2013SQL Tuning 101 - Sep 2013
SQL Tuning 101 - Sep 2013
 
Analytic SQL Sep 2013
Analytic SQL Sep 2013Analytic SQL Sep 2013
Analytic SQL Sep 2013
 
実践 memcached
実践 memcached実践 memcached
実践 memcached
 
Get your moneys worth out of your database
Get your moneys worth out of your databaseGet your moneys worth out of your database
Get your moneys worth out of your database
 
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matchingLatin America Tour 2019 - pattern matching
Latin America Tour 2019 - pattern matching
 
Oracle Database 12c Application Development
Oracle Database 12c Application DevelopmentOracle Database 12c Application Development
Oracle Database 12c Application Development
 
zen and the art of SQL optimization
zen and the art of SQL optimizationzen and the art of SQL optimization
zen and the art of SQL optimization
 
Latin America tour 2019 - Flashback
Latin America tour 2019 -  FlashbackLatin America tour 2019 -  Flashback
Latin America tour 2019 - Flashback
 
SQL techniques for faster applications
SQL techniques for faster applicationsSQL techniques for faster applications
SQL techniques for faster applications
 
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
 
SQL WORKSHOP::Lecture 4
SQL WORKSHOP::Lecture 4SQL WORKSHOP::Lecture 4
SQL WORKSHOP::Lecture 4
 
Pattern Matching with SQL - APEX World Rotterdam 2019
Pattern Matching with SQL - APEX World Rotterdam 2019Pattern Matching with SQL - APEX World Rotterdam 2019
Pattern Matching with SQL - APEX World Rotterdam 2019
 
Decipher Multi-Factor Authentication - A Developers Introduction
Decipher Multi-Factor Authentication - A Developers IntroductionDecipher Multi-Factor Authentication - A Developers Introduction
Decipher Multi-Factor Authentication - A Developers Introduction
 
E-Commerce Security - Application attacks - Server Attacks
E-Commerce Security - Application attacks - Server AttacksE-Commerce Security - Application attacks - Server Attacks
E-Commerce Security - Application attacks - Server Attacks
 
Sangam 18 - Database Development: Return of the SQL Jedi
Sangam 18 - Database Development: Return of the SQL JediSangam 18 - Database Development: Return of the SQL Jedi
Sangam 18 - Database Development: Return of the SQL Jedi
 
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
 

Ähnlich wie SQL techniques for faster applications

Profiling of Oracle Function Calls
Profiling of Oracle Function CallsProfiling of Oracle Function Calls
Profiling of Oracle Function Calls
Enkitec
 
11 Things About 11gr2
11 Things About 11gr211 Things About 11gr2
11 Things About 11gr2
afa reg
 
Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...
Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...
Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...
Ontico
 

Ähnlich wie SQL techniques for faster applications (20)

Perth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL TechniquesPerth APAC Groundbreakers tour - SQL Techniques
Perth APAC Groundbreakers tour - SQL Techniques
 
C PROGRAMS - SARASWATHI RAMALINGAM
C PROGRAMS - SARASWATHI RAMALINGAMC PROGRAMS - SARASWATHI RAMALINGAM
C PROGRAMS - SARASWATHI RAMALINGAM
 
Profiling of Oracle Function Calls
Profiling of Oracle Function CallsProfiling of Oracle Function Calls
Profiling of Oracle Function Calls
 
Adapting to Adaptive Plans on 12c
Adapting to Adaptive Plans on 12cAdapting to Adaptive Plans on 12c
Adapting to Adaptive Plans on 12c
 
MySQL and GIS Programming
MySQL and GIS ProgrammingMySQL and GIS Programming
MySQL and GIS Programming
 
Connor McDonald 11g for developers
Connor McDonald 11g for developersConnor McDonald 11g for developers
Connor McDonald 11g for developers
 
Explain this!
Explain this!Explain this!
Explain this!
 
Riyaj: why optimizer_hates_my_sql_2010
Riyaj: why optimizer_hates_my_sql_2010Riyaj: why optimizer_hates_my_sql_2010
Riyaj: why optimizer_hates_my_sql_2010
 
11 Things About 11gr2
11 Things About 11gr211 Things About 11gr2
11 Things About 11gr2
 
Need for Speed: MySQL Indexing
Need for Speed: MySQL IndexingNeed for Speed: MySQL Indexing
Need for Speed: MySQL Indexing
 
ILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for DevelopersILOUG 2019 - SQL features for Developers
ILOUG 2019 - SQL features for Developers
 
Using SQL to process hierarchies
Using SQL to process hierarchiesUsing SQL to process hierarchies
Using SQL to process hierarchies
 
Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...
Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...
Deep dive into PostgreSQL internal statistics / Алексей Лесовский (PostgreSQL...
 
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
 
OpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developersOpenWorld Sep14 12c for_developers
OpenWorld Sep14 12c for_developers
 
11 things about 11gr2
11 things about 11gr211 things about 11gr2
11 things about 11gr2
 
Data manipulation with dplyr
Data manipulation with dplyrData manipulation with dplyr
Data manipulation with dplyr
 
Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.Deep dive into PostgreSQL statistics.
Deep dive into PostgreSQL statistics.
 
R meets Hadoop
R meets HadoopR meets Hadoop
R meets Hadoop
 
Pro PostgreSQL
Pro PostgreSQLPro PostgreSQL
Pro PostgreSQL
 

Mehr von Connor McDonald

Mehr von Connor McDonald (17)

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
 
OOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL featuresOOW19 - Ten Amazing SQL features
OOW19 - Ten Amazing SQL features
 
Latin America Tour 2019 - 18c and 19c featues
Latin America Tour 2019   - 18c and 19c featuesLatin America Tour 2019   - 18c and 19c featues
Latin America Tour 2019 - 18c and 19c featues
 
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
 
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
 
Kscope19 - Flashback: Good for Developers as well as DBAs
Kscope19 - Flashback: Good for Developers as well as DBAsKscope19 - Flashback: Good for Developers as well as DBAs
Kscope19 - Flashback: Good for Developers as well as DBAs
 
Kscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processingKscope19 - Understanding the basics of SQL processing
Kscope19 - Understanding the basics of SQL processing
 
18c and 19c features for DBAs
18c and 19c features for DBAs18c and 19c features for DBAs
18c and 19c features for DBAs
 
APEX Connect 2019 - SQL Tuning 101
APEX Connect 2019 - SQL Tuning 101APEX Connect 2019 - SQL Tuning 101
APEX Connect 2019 - SQL Tuning 101
 
APEX Connect 2019 - successful application development
APEX Connect 2019 - successful application developmentAPEX Connect 2019 - successful application development
APEX Connect 2019 - successful application development
 

Kürzlich hochgeladen

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Kürzlich hochgeladen (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
Deploy with confidence: VMware Cloud Foundation 5.1 on next gen Dell PowerEdg...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 

SQL techniques for faster applications

  • 1. WE ARE SHOWING CODING SAMPLES SO IF YOU HAVE PASSED THE AGE OF TWENTY THEN YOU SHOULD PROBABLY THINK ABOUT SITTING RIGHT UP CLOSE TO THE FRONT OF THE ROOM BECAUSE OTHERWISE YOU MIGHT MISS OUT A N D I F Y O U C A N R E A D T H I S, T H E N Y O U S H O U L D L E A V E B E C A U S E Y O U H A V E S U P E R P O W E R S A N D Y O U S H O U L D B E I N A N A V E N G E R S M O V I E N O T L E A R N I N G A B O U T I N F O R M A T I O N T E C H N O L O G Y. :-)
  • 2. 2
  • 4. 4
  • 5. 5
  • 9. why talk about SQL 9 # 1
  • 11. 11
  • 13. 13
  • 14. why talk about SQL 14 # 2
  • 18. ... not for data processing 18
  • 19. a little bit of SQL ... 19
  • 20. ... can make your apps awesome 20
  • 22. this session is about ... 22
  • 24. SQL can do anything ... 24
  • 25. 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) 25
  • 26. 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 ) 26 Ack: Anton Scheffer, https://technology.amis.nl
  • 27. 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; 27 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
  • 29. 29 100% % of developers that will need to solve Sudoku as part of their job
  • 30. 30 100% % of developers that need to get real stuff done
  • 32. 32 1
  • 35.
  • 39. 39 2
  • 41. "What if I don't have a TAB200K ?" 41 insert into my_transactions1 select ... from tab200k;
  • 44. 44 SQL> select * from meetings; SCHEDULED OWNER --------- ------------------------- 06-MAY-17 Connor 13-MAY-17 Gerald 17-MAY-17 Maria
  • 45. 45 Connor Gerald Maria free free free free free free free free free free free free free free free free free free free free free free freefree free free freefree
  • 47. 47 SQL> select * from meetings; SCHEDULED OWNER --------- ----------------------- 01-MAY-17 02-MAY-17 03-MAY-17 04-MAY-17 05-MAY-17 06-MAY-17 Connor 07-MAY-17 08-MAY-17 ... 16-MAY-17 17-MAY-17 Maria 18-MAY-17 19-MAY-17 ... 30-MAY-17 31-MAY-17
  • 48. 31 ? 365 ? 48
  • 49. any number of rows 49
  • 51. SQL> select level seq 2 from DUAL 3 connect by level <= 10; SEQ ---------- 1 2 3 4 5 6 7 8 9 10 10 rows selected. 51 Oracle
  • 52. select * from generate_series(1, 10) 52 with gen(seq) as ( select 1 seq union all select seq+1 from gen where seq < 10 ) select * from gen; select seq from my_n_row_table Postgres SQL Server MySQL
  • 53. SQL> select level seq 2 from DUAL 3 connect by level <= 10; ----------------------------------------------------- | Id | Operation | Name | Rows | ----------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | |* 1 | CONNECT BY WITHOUT FILTERING| | | | 2 | FAST DUAL | | 1 | ----------------------------------------------------- Statistics ------------------------------ 1 recursive calls 0 db block gets 0 consistent gets 0 physical reads 53
  • 55. if I have integers ... 55
  • 56. ... I have dates 56
  • 57. SQL> select date '2017-04-30'+level dte 2 from dual 3 connect by level <= 31; DTE --------- 01-MAY-17 02-MAY-17 03-MAY-17 04-MAY-17 ... ... 29-MAY-17 30-MAY-17 31-MAY-17 31 rows selected. 57
  • 59. 59 SQL> select 2 dte scheduled, 3 m.owner 4 from 5 ( select date '2017-04-30'+level dte 6 from dual 7 connect by level <= 31 ) d 8 left outer join 9 meetings m 10 on d.dte = m.scheduled 11 order by 1; SCHEDULED OWNER --------- ----------------------- 01-MAY-17 02-MAY-17 03-MAY-17 04-MAY-17 05-MAY-17 06-MAY-17 Connor 07-MAY-17 08-MAY-17 ... 16-MAY-17 17-MAY-17 Maria 18-MAY-17 19-MAY-17 ... 30-MAY-17 31-MAY-17
  • 60. 60 3
  • 64. 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 64
  • 65. "gee....... more code, same result" 65
  • 66. WITH last_hire AS ( select deptno, max(hiredate) from emp group by deptno ) select * from last_hire; 66
  • 67. why is it cool ? 67
  • 69. relational is a rigorous model ... 69
  • 71. relational ... can sortta suck :-) 71
  • 74. "data is represented as mathematical n-ary relations, an n-ary relation being a subset of the Cartesian product of n domains." 74
  • 77. "First, get the total salary paid by each department, then get the average of these totals, then list those departments above that average" 77 SQL ?
  • 78. "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), 78
  • 79. "...then get the average of these totals... 6 avg_sal AS ( SELECT AVG(dept_sal) avsal 7 FROM dept_salaries) 79
  • 80. "...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; 80
  • 81. 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; 81
  • 85. recall : 31 days of meetings 85
  • 86. 86 SQL> with raw_data as ( 2 select 3 dte scheduled, 4 m.owner 5 from 6 ( select date '2017-04-30'+level dte 7 from dual 8 connect by level <= 31 ) d 9 left outer join 10 meetings m 11 on d.dte = m.scheduled 12 ) 13 select 14 json_arrayagg( 15 json_object(key to_char(scheduled) value owner ) 16 order by scheduled ) as meetings 17 from raw_data ; [{"01-MAY-17":null}, {"02-MAY-17":null}, {"03-MAY-17":null}, {"04-MAY-17":null}, {"05-MAY-17":null}, {"06-MAY-17":"Connor"}, {"07-MAY-17":null}, {"08-MAY-17":null}, {"09-MAY-17":null}, {"10-MAY-17":null}, ... ... ... {"30-MAY-17":null}, {"31-MAY-17":null} ]
  • 90. 90 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; join
  • 91. ---------------------------------------------------------------------- | Id | Operation | Name | ---------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | TEMP TABLE TRANSFORMATION | | | 2 | LOAD AS SELECT | | | 3 | HASH GROUP BY | | | 4 | MERGE JOIN | | | 5 | TABLE ACCESS BY INDEX ROWID| DEPT | | 6 | INDEX FULL SCAN | PK_DEPT | | 7 | SORT JOIN | | | 8 | TABLE ACCESS FULL | EMP | | 9 | SORT ORDER BY | | | 10 | NESTED LOOPS | | | 11 | VIEW | | | 12 | SORT AGGREGATE | | | 13 | VIEW | | | 14 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6624_AF422F5 | | 15 | VIEW | | | 16 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6624_AF422F5 | ---------------------------------------------------------------------- 91
  • 92. SQL> alter session set sql_trace = true; Session altered. 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) asal 7 FROM dept_salaries) 8 SELECT * FROM dept_salaries d, avg_sal a 9 WHERE d.dept_sal > a.asal 10 ORDER BY d.dname; DNAME DEPT_SAL ASAL -------------- ---------- ---------- RESEARCH 21750 19350 SQL> alter session set sql_trace = false; Session altered. 92
  • 93. PARSING IN CURSOR #12 len=179 dep=1 uid=0 oct=1... CREATE GLOBAL TEMPORARY TABLE "SYS"."SYS_TEMP_0FD9D6625_AF422F5" ("C0" VARCHAR2(14),"C1" NUMBER ) IN_MEMORY_METADATA CURSOR_SPECIFIC_SEGMENT STORAGE (OBJNO 4254950949 ) NOPARALLEL END OF STMT 93
  • 95. ------------------------------------------------------ | Id | Operation | Name | ------------------------------------------------------ | 0 | SELECT STATEMENT | | | 1 | SORT ORDER BY | | | 2 | NESTED LOOPS | | | 3 | VIEW | | | 4 | SORT AGGREGATE | | | 5 | VIEW | | | 6 | HASH GROUP BY | | | 7 | MERGE JOIN | | | 8 | TABLE ACCESS BY INDEX ROWID| DEPT | | 9 | INDEX FULL SCAN | PK_DEPT | | 10 | SORT JOIN | | | 11 | TABLE ACCESS FULL | EMP | | 12 | VIEW | | | 13 | SORT GROUP BY | | | 14 | MERGE JOIN | | | 15 | TABLE ACCESS BY INDEX ROWID | DEPT | | 16 | INDEX FULL SCAN | PK_DEPT | | 17 | SORT JOIN | | | 18 | TABLE ACCESS FULL | EMP | ------------------------------------------------------ 95
  • 96. 96 4
  • 98. 98 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
  • 100. 100 SQL> SELECT hrs.hr, t1.room, t1.who 2 from timeslots hrs 3 left outer join bookings t1 4 on hrs.hr = t1.hr HR ROOM WHO ------- ---------- ---------- 8 Room2 PETE 9 Room1 JOHN 10 11 Room1 MIKE 12 13 14 Room2 JILL 15 Room2 JANE 16 Room1 SAM 100
  • 101. bookings by hour per room 101
  • 102. 102 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
  • 103. 103 SQL> select * 2 from timeslots; HR -- 8 9 10 11 12 13 14 15 16 x "Room 1" x "Room 2" ... x "Room n"
  • 105. 105 SQL> SELECT hrs.hr, t1.room, t1.who 2 FROM bookings t1 3 PARTITION BY (t1.room) 4 RIGHT OUTER JOIN hrs ON (hrs.hr = t1.hr); 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 105
  • 106. 106 5
  • 108. 108 "employees by hiredate, recent first"
  • 109. SQL> select empno, ename, hiredate 2 from emp 3 limit 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 109
  • 110. 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 110
  • 112. 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 112
  • 113. 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; 113
  • 114. 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 114
  • 115. 115 "TL;DR ... my app can do it"
  • 116. 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(); } 116
  • 117.
  • 118. 118
  • 120. let the database know 120
  • 121. SQL> select * 2 from ( 3 select empno, ename, hiredate 4 from emp 5 order by hiredate desc 6 ) 7 where rownum <= 5; 121 ------------------------------------------------ | 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 | ------------------------------------------------
  • 122. SQL> select empno, ename, hiredate 2 from emp 3 order by hiredate desc 4 fetch first 5 rows only; 122 ------------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | |* 1 | VIEW | | 14 | |* 2 | WINDOW SORT PUSHED RANK| | 14 | | 3 | TABLE ACCESS FULL | EMP | 14 | -------------------------------------------------
  • 123. you get other benefits 123 oc02.sql
  • 124. 124 "but what about the next page ?"
  • 127. 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 127
  • 128. 128 "an expensive query per page ?!?!
  • 130. 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 130 /*+ result_cache */ rownum r, f.* oc03.sql r between 11 and 20
  • 131. 131 6
  • 133. C#, C++ ESB Tuxedo Weblogic Stored Procedure 133
  • 134. 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;134
  • 136. 136
  • 139. SQL can be complex 139
  • 140. SQL should "self document" 140
  • 142. 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 142
  • 143. 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 | 143
  • 144. ? 144 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 |
  • 145. 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 145 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
  • 146. 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 146
  • 147. assist with query trace 147
  • 148. SQL> alter session set 2 events = '10053 trace name context forever, level 1'; Session altered. 148
  • 149. ************************** Query transformations (QT) ************************** CBQT: Validity checks passed for 7jpzpr2475cqw. CSE: Sub-expression elimination in query block SEL$1 (#0) ************************* Common Subexpression elimination (CSE) ************************* CSE: CSE not performed on query block YR_HIRE (#0). CSE: Sub-expression elimination in query block AV_SAL (#0) CSE: CSE not performed on query block AV_SAL (#0). CSE: CSE not performed on query block SEL$1 (#0). *************************** Order-by elimination (OBYE) *************************** OBYE: Considering Order-by Elimination from view SEL$1 (#0) 149
  • 150. ********************************* Number of join permutations tried: 1 ********************************* GROUP BY adjustment factor: 1.000000 GROUP BY cardinality: 3.000000, TABLE cardinality: 14.000000 SORT ressource Sort statistics Sort width: 598 Area size: 1048576 Max Area: 104857600 Degree: 1 Blocks to Sort: 1 Row size: 18 Total Rows: 14 Initial runs: 1 Merge passes: 0 IO Cost / pass: 0 Total IO sort cost: 0 Total CPU sort cost: 14312402 Total Temp space used: 0 Trying or-Expansion on query block AV_SAL (#3) Transfer Optimizer annotations for query block AV_SAL (#3) GROUP BY adjustment factor: 1.000000 Final cost for query block AV_SAL (#3) - All Rows Plan: Best join order: 1 Cost: 4.0029 Degree: 1 Card: 14.0000 Bytes: 98 Resc: 4.0029 Resc_io: 3.0000 Resc_cpu: 14352069 Resp: 4.0029 Resp_io: 3.0000 Resc_cpu: 14352069 150
  • 152. 152 select /*+ QB_NAME(top) INDEX(@yr_hire emp (empno)) FULL(@av_sal emp) */ INDEX(emp emp_ix)
  • 153. 153 7
  • 155. "Employee salary list, plus department total, plus grand total" 155
  • 156. 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 156 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
  • 157. from 3 to 2 157 rollup
  • 158. 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 158 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
  • 160. EMPNO SAL DEPTNO ---------- ---------- ---------- 7782 2450 10 7839 5000 10 7934 1300 10 7566 2975 20 7902 3000 20 7876 1100 20 7369 800 20 160 DEPTNO SUM(SAL) ---------- ---------- 10 8750 20 10875 30 9400 29025 7782 2450 10 7839 5000 10 7934 1300 10 7566 2975 20 10 8750
  • 161. from 2 to 1 161
  • 162. 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 29025162
  • 163. the whole lot ! 163
  • 164. 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 164
  • 166. 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 166
  • 167. 167 8
  • 169. 169
  • 170. 170
  • 171. 171
  • 173. "Find 10 consecutive deposits in a 24 hour period, then a withdrawal within three days of the last deposit, at a different retail outlet" 173
  • 174. 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 174
  • 177. 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 ) 177
  • 178. 178 9
  • 179. 179
  • 180. 180 "talking" to your database ... makes it faster
  • 183. 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 183 hash outer join ? nested loop ? STORES first ? sort merge ?
  • 184. --------------------------------------------------- | 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 | --------------------------------------------------- 184
  • 185. 185 can we do better ? add indexes ? rewrite query ? result cache ? materialized view ?
  • 186. 186 share your knowledge with the db oc04.sql
  • 187. 187 10
  • 189. rows to columns, colums to rows 189
  • 190. "I need sales by product for each quarter....now" 190
  • 191. 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 ... 191
  • 192. "That’s wrong!...surely you know I wanted it ACROSS the page" 192
  • 193. 193
  • 194. 194
  • 196. 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 196
  • 198. "That’s wrong!...surely you know I wanted it DOWN the page" 198
  • 199. SQL> desc SALES_ACROSS Name Null? Type ----------------------------- -------- ------------- PRODUCT VARCHAR2(20) Q1 NUMBER Q2 NUMBER Q3 NUMBER Q4 NUMBER 199
  • 201. 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" 201
  • 202. elements must be known in advance 202
  • 203. 203 11
  • 205. SQL> select 2 ( select dname 3 from dept 4 where deptno = e.deptno ) dname, 5 decode(empno, 7499, 6 ( select max(sal) from emp ), 7 -1) 8 from 9 ( select * from emp 10 where sal > 0 ) e 11 where 12 ( select max(hiredate) from emp ) < sysdate 13 / scalar anywhere an expression could be 205
  • 207. SQL> create or replace 2 function CALC_TAX(p int) return number is 3 begin 4 dbms_lock.sleep(1); 5 return p; 6 end; 7 / Function created. SQL> create table T 2 as select rownum r, mod(rownum,5) r1 from dual 3 connect by level <= 30; Table created. 1,2,3,..., 30 0,1,2,3,4,0,1,2,3,4, ... 207
  • 208. SQL> select r, calc_tax(r1) tax from T; R TAX ---------- ---------- 1 1 2 2 3 3 4 4 ... 28 3 29 4 30 0 30 rows selected. Elapsed: 00:00:30.01 208
  • 209. SQL> select r, 2 ( select calc_tax(r1) from dual) as tax 3 from T; R TAX ---------- ---------- 1 1 2 2 ... 28 3 29 4 30 0 30 rows selected. Elapsed: 00:00:05.01 209
  • 210. subquery caching ... any subquery 210
  • 211. what about multiple values 211
  • 212. SQL> select 2 empno, 3 ( select dname, loc, revenue 4 from dept 5 where deptno = e.deptno ) 6 from EMP e; ( select dname, loc, revenue * ERROR at line 3: ORA-00913: too many values 212
  • 213. SQL> select 2 empno, 3 ( select dname 4 from dept 5 where deptno = e.deptno ) dname, 6 ( select loc 7 from dept 8 where deptno = e.deptno ) loc, 9 ( select revenue 10 from dept 11 where deptno = e.deptno ) rev 12 from EMP e; EMPNO DNAME LOC REV ---------- -------------- ------------- ---------- 7839 ACCOUNTING NEW YORK 10000 7698 SALES CHICAGO 30000 7782 ACCOUNTING NEW YORK 10000 ... 213
  • 215. SQL> create type multi_attrib as object ( 2 dname varchar2(10), 3 loc varchar2(10), 4 rev number ); 5 / Type created. 215
  • 216. SQL> select empno, 2 x.attr.dname, 3 x.attr.loc, 4 x.attr.rev 5 from 6 ( 7 select 8 empno, 9 ( select multi_attrib(dname,loc,revenue) 10 from dept 11 where deptno = e.deptno ) attr 12 from EMP e 13 ) x; EMPNO ATTR.DNAME ATTR.LOC ATTR.REV ---------- ---------- ---------- ---------- 7839 ACCOUNTING NEW YORK 10000 7698 SALES CHICAGO 30000 7782 ACCOUNTING NEW YORK 10000 216
  • 217. 217 12
  • 219. 219
  • 220. SQL> select rpad(' ',level)||ename, 2 from emp 3 start with mgr is null 4 connect by prior empno = mgr ENAME --------------------------- KING BLAKE JAMES ALLEN WARD CLARK MILLER 220
  • 221. SQL> select empno, ename, mgr 2 from emp 3 where mgr is null; EMPNO ENAME MGR ---------- -------------------- ---------- 7839 KING 221
  • 222. SQL> select e2.empno, e2.ename, e2.mgr 2 from emp e2, 3 ( select empno, mgr 4 from emp 5 where mgr is null ) inner 6 where e2.mgr = inner.empno; EMPNO ENAME MGR ---------- -------------------- ---------- 7566 JONES 7839 7698 BLAKE 7839 7782 CLARK 7839 222
  • 223. SQL> select e3.empno, e3.ename, e3.mgr 2 from emp e3, 3 ( select e2.empno, e2.ename, e2.mgr 4 from emp e2, 5 ( select empno, mgr 6 from emp 7 where mgr is null ) inner 8 where e2.mgr = inner.empno ) inner 9 where e3.mgr = inner.empno; EMPNO ENAME MGR ---------- -------------------- ---------- 7902 FORD 7566 7788 SCOTT 7566 7900 JAMES 7698 7844 TURNER 7698 7654 MARTIN 7698 7521 WARD 7698 7934 MILLER 7782 223
  • 224. SQL> select e4.empno, e4.ename, e4.mgr 2 from emp e4, 3 ( select e3.empno, e3.ename, e3.mgr 4 from emp e3, 5 ( select e2.empno, e2.ename, e2.mgr 6 from emp e2, 7 ( select empno, mgr 8 from emp 9 where mgr is null ) inner 10 where e2.mgr = inner.empno ) inner 11 where e3.mgr = inner.empno ) inner 12 where e4.mgr = inner.empno; EMPNO ENAME MGR ---------- -------------------- ---------- 7876 ADAMS 7788 recursive... 224
  • 226. WITH can be recursive 226
  • 227. SQL> with EACH_LEVEL (empno, name, mgr) as 2 ( -- 3 -- start with 4 -- 5 select empno, ename, mgr 6 from emp 7 where mgr is null 8 -- 9 -- connect by 10 -- 11 union all 12 select emp.empno, emp.ename, emp.mgr 13 from emp, EACH_LEVEL 14 where emp.mgr = each_level.empno 15 ) 16 select * 17 from each_level; 227
  • 228. EMPNO NAME MGR ---------- --------------- ---------- 7839 KING 7566 JONES 7839 7698 BLAKE 7839 7782 CLARK 7839 7499 ALLEN 7698 7521 WARD 7698 7654 MARTIN 7698 7788 SCOTT 7566 7844 TURNER 7698 7900 JAMES 7698 7902 FORD 7566 7934 MILLER 7782 7369 SMITH 7902 7876 ADAMS 7788 228
  • 230. with RECURSIVE_WITH (c1,c2,c3) as ( <starting/entry point> union all <recursive relationship> ) select ... from RECURSIVE_WITH 230
  • 232. SQL> with each_level (empno, name, mgr, rlevel) as 2 ( select empno, ename, mgr, 1 rlevel 3 from emp 4 where mgr is null 5 union all 6 select emp.empno, emp.ename, emp.mgr, rlevel+1 7 from emp, each_level 8 where emp.mgr = each_level.empno 9 ) 10 select * from each_level; EMPNO NAME MGR RLEVEL ---------- --------------- ---------- ---------- 7839 KING 1 7566 JONES 7839 2 7698 BLAKE 7839 2 7782 CLARK 7839 2 7499 ALLEN 7698 3 ... 232
  • 233. SQL> with each_level (empno, name) as 2 ( select empno, ename from emp 3 where mgr is null 4 union all 5 select e.empno, 6 each_level.name||'-'||e.ename 7 from emp e, each_level 8 where e.mgr = each_level.empno 9 ) 10 select empno, name from each_level; EMPNO NAME ---------- -------------------------------- 7839 KING 7566 KING-JONES 7698 KING-BLAKE 7782 KING-CLARK 7499 KING-BLAKE-ALLEN 7521 KING-BLAKE-WARD ...233
  • 235. SQL> with each_level (empno, name, mgr) as 2 ( select empno, ename, mgr 3 from emp 4 where ename = 'KING' 5 union all 6 select emp.empno, emp.ename, emp.mgr 7 from emp, each_level 8 where emp.mgr = each_level.empno 9 ) 10 select * 11 from each_level; ERROR: ORA-32044: cycle detected while executing recursive WITH query 235
  • 236. SQL> with each_level (empno, name, mgr) as 2 ( select empno, ename, mgr from emp 3 where ename = 'KING' 4 union all 5 select emp.empno, emp.ename, emp.mgr 6 from emp, each_level 7 where emp.mgr = each_level.empno ) 8 CYCLE mgr SET is_cycle TO 'Y' DEFAULT 'N' 9 select * from each_level; EMPNO NAME MGR IS_CYCLE ---------- ---------- ---------- ---------- 7839 KING 7499 N 7566 JONES 7839 N 7521 WARD 7698 N 7839 KING 7499 Y 7876 ADAMS 7788 N ... 236
  • 238. SQL> with each_level (empno, name, hiredate, mgr) as 2 ( select empno, ename, hiredate, mgr from emp 3 where ename = 'KING' 4 union all 5 select e.empno, 6 each_level.name||'-'||e.ename, e.hiredate, e.mgr 7 from emp e, each_level 8 where e.mgr = each_level.empno ) 9 SEARCH BREADTH FIRST BY HIREDATE SET IDX 10 select name, hiredate, idx from each_level; NAME HIREDATE IDX -------------------------------- --------- ---------- KING 17-NOV-81 1 KING-JONES 02-APR-81 2 KING-BLAKE 01-MAY-81 3 KING-CLARK 09-JUN-81 4 KING-BLAKE-ALLEN 20-FEB-81 5 KING-BLAKE-WARD 22-FEB-81 6 ... KING-JONES-FORD-SMITH 17-DEC-80 13 KING-JONES-SCOTT-ADAMS 23-MAY-87 14 238
  • 239. SQL> with each_level (empno, name, hiredate, mgr) as 2 ( select empno, ename, hiredate, mgr from emp 3 where ename = 'KING' 4 union all 5 select e.empno, 6 each_level.name||'-'||e.ename, e.hiredate, e.mgr 7 from emp e, each_level 8 where e.mgr = each_level.empno ) 9 SEARCH DEPTH FIRST BY HIREDATE SET IDX 10 select name, hiredate, idx from each_level; NAME HIREDATE IDX -------------------------------- --------- ---------- KING 17-NOV-81 1 KING-JONES 02-APR-81 2 KING-JONES-FORD 03-DEC-81 3 KING-JONES-FORD-SMITH 17-DEC-80 4 KING-JONES-SCOTT 19-APR-87 5 KING-JONES-SCOTT-ADAMS 23-MAY-87 6 KING-BLAKE 01-MAY-81 7 KING-BLAKE-ALLEN 20-FEB-81 8 etc 239
  • 240. 240
  • 242. SQL> select * from messages; TXT ---------------------------------------------------------- I caught up with Connor and Maria Colgan today. They have taken over AskTOM for Oracle Developers 242
  • 243. SQL> select * from twitter_handles; ID TERM HANDLE ---- ------------------------------ --------------- 1 Connor McDonald @connor_mc_d 2 Connor @connor_mc_d 3 Maria Colgan @sqlmaria 4 Oracle Developers @otndev 5 Oracle @oracle 6 AskTOM @oracleasktom 243
  • 244. SQL> with 2 tweetised(ind,tweet_txt) as 3 ( 4 select 1 ind, txt tweet_txt 5 from messages 6 union all 7 select ind+1, replace(tweet_txt,term,handle) 8 from tweetised, twitter_handles 9 where ind = id 10 ) 11 select * from tweetised; 244
  • 245. IND TWEET_TXT --------- ----------------------------------------------------------------------------------------- 1 I caught up with Connor and Maria Colgan today. They have taken over AskTOM for... 2 I caught up with Connor and Maria Colgan today. They have taken over AskTOM for... 3 I caught up with @connor_mc_d and Maria Colgan today. They have taken over AskTOM for... 4 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for ... 5 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for @otndev 6 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for @otndev 7 I caught up with @connor_mc_d and @sqlmaria today. They have taken over @oracleasktom ... 245
  • 246. SQL> with 2 tweetised(ind,tweet_txt) as 3 ( 4 select 1 ind, txt tweet_txt 5 from messages 6 union all 7 select ind+1, replace(tweet_txt,term,handle) 8 from tweetised, twitter_handles 9 where ind = id 10 ) 11 select * from tweetised 12 order by ind desc 13 fetch first 1 row only; IND TWEET_TXT ---------- ------------------------------------------------------ 7 I caught up with @connor_mc_d and @sqlmaria today. They... 246
  • 248. staying up to date 248
  • 249. 249
  • 250. 250 "fill in the blanks"
  • 251. 251 SQL> select dt, val 2 from t 3 order by dt; DT VAL --------- ---------- 02-JAN-11 195 03-JAN-11 04-JAN-11 05-JAN-11 06-JAN-11 129 07-JAN-11 08-JAN-11 09-JAN-11 10-JAN-11 87 11-JAN-11 ... 195 195 195 129 129 129 87
  • 252. 252 SQL> select dt, val, 2 case when val is not null 3 then to_char(row_number() over (order by dt),'fm0000')||'-'||val 4 end max_val 5 from t 6 order by dt; DT VAL MAX_VAL --------- ---------- ----------- 02-JAN-11 195 0001-195 03-JAN-11 04-JAN-11 05-JAN-11 06-JAN-11 129 0005-129 07-JAN-11 08-JAN-11 09-JAN-11 10-JAN-11 87 0009-87 11-JAN-11 ...
  • 253. 253 SQL> select dt, val, 2 max(max_val) over (order by dt) max_val_str 3 from ( select dt, val, 4 case when val is not null 5 then to_char(row_number() over (order by dt),'fm0000')||'-'||val 6 end max_val 7 from t ) order by dt; DT VAL MAX_VAL_STR --------- ---------- ------------------ 02-JAN-11 195 0001-195 03-JAN-11 0001-195 04-JAN-11 0001-195 05-JAN-11 0001-195 06-JAN-11 129 0005-129 07-JAN-11 0005-129 08-JAN-11 0005-129 09-JAN-11 0005-129 10-JAN-11 87 0009-87 11-JAN-11 0009-87 ...
  • 254. 254 SQL> select dt, val, 2 to_number(substr(max(max_val) over (order by dt),5)) max_val 3 from ( select dt, val, 4 case when val is not null 5 then to_char(row_number() over (order by dt),'fm0000')||val 6 end max_val 7 from t ) order by dt 8 / DT VAL MAX_VAL --------- ---------- ---------- 02-JAN-11 195 195 03-JAN-11 195 04-JAN-11 195 05-JAN-11 195 06-JAN-11 129 129 07-JAN-11 129 08-JAN-11 129 09-JAN-11 129 10-JAN-11 87 87 11-JAN-11 87
  • 255. 255 SQL> select dt, val, 2 last_value(val ignore nulls) over (order by dt) val 3 from t 4 order by dt; DT VAL VAL --------- ---------- ---------- 02-JAN-11 195 195 03-JAN-11 195 04-JAN-11 195 05-JAN-11 195 06-JAN-11 129 129 07-JAN-11 129 08-JAN-11 129 09-JAN-11 129 10-JAN-11 87 87 11-JAN-11 87
  • 262. never too early to start 262
  • 263.
  • 264. SQL> Connected. SQL> ORACLE instance shut down. SQL> conn / as sysdba shutdown abort @connor_mc_d

Hinweis der Redaktion

  1. Everyone is a beginner