... Through SQL: Connor Mcdonald
... Through SQL: Connor Mcdonald
Connor McDonald
...through SQL
1
3 4
https://www.youtube.com/c/ConnorMcDonaldOracle
@connor_mc_d connormcdonald.wordpress.com
https://www.facebook.com/connor.mcdonald42
5 6
1
5/11/2017
# 1
asktom.oracle.com
7 8
9 10
NoSQL
non relational
11 12
2
5/11/2017
# 2
13 14
15 16
17 18
3
5/11/2017
19 20
21 22
4
5/11/2017
SOLUTION
----------- 100%
534|678|912
672|195|348
198|342|567
-----------
859|761|423
426|853|791
713|924|856
-----------
961|537|284 % of developers that
287|419|635 will need to solve Sudoku
345|286|179 as part of their job
-----------
sud.sql
25 26
100%
27 28
1 some controversy...
29 30
5
5/11/2017
DBA
31
oc00.sql
2
33 34
35 36
6
5/11/2017
37 38
SCHEDULED OWNER
--------- -----------------------
01-MAY-17
02-MAY-17
03-MAY-17
04-MAY-17
05-MAY-17
what we need
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
41
31-MAY-17
42
7
5/11/2017
43 44
SEQ
----------
1
2
3
easy 4
5
6
7
8
9
10
-----------------------------------------------------
with gen(seq) as ( | Id | Operation | Name | Rows |
select 1 seq -----------------------------------------------------
union all | 0 | SELECT STATEMENT | | 1 |
select seq+1 from gen
where seq < 10
SQL Server |* 1 | CONNECT BY WITHOUT FILTERING| | |
| 2 | FAST DUAL | | 1 |
) -----------------------------------------------------
select * from gen;
Statistics
------------------------------
1 recursive calls
select seq 0 db block gets
from my_n_row_table MySQL 0 consistent gets
0 physical reads
47 48
8
5/11/2017
49 50
DTE
---------
01-MAY-17
02-MAY-17
31 rows selected.
51 52
SQL> select
2 dte scheduled, SCHEDULED OWNER
3 m.owner --------- -----------------------
4 from 01-MAY-17
5 02-MAY-17
( select date '2017-04-30'+level dte
6 from dual 03-MAY-17
7 04-MAY-17
connect by level <= 31 ) d
8 left outer join 05-MAY-17
9 meetings m 06-MAY-17 Connor
9
5/11/2017
3 subquery factoring
55 56
57 58
59 60
10
5/11/2017
WITH last_hire AS
(
select deptno, max(hiredate)
from emp
group by deptno why is it cool ?
)
select * from last_hire;
61 62
63 64
65 66
11
5/11/2017
67 68
huh ?
"data is represented as mathematical n-ary
relations, an n-ary relation being a subset of the
Cartesian product of n domains."
69 70
SQL ?
71 72
12
5/11/2017
"First, get the total salary paid by department... "...then get the average of these totals...
73 74
75 76
77 78
13
5/11/2017
79 80
83 84
14
5/11/2017
85 86
87 88
END OF STMT
89 90
15
5/11/2017
------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | NESTED LOOPS | |
4
| 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 |
------------------------------------------------------
91 92
SQL> select *
2 from timeslots;
HR
--
8
9
10 SQL> select *
11 2 from bookings;
12
partitioned outer join 13
14
HR
-------
ROOM
----------
WHO
-------
15 8 Room2 PETE
16 9 Room1 JOHN
11 Room1 MIKE
14 Room2 JILL
15 Room2 JANE
16 Room1 SAM
93 94
HR ROOM WHO
------- ---------- ----------
bookings by hour
8 Room2 PETE
9 Room1 JOHN
10
11 Room1 MIKE
12
13
14 Room2 JILL
conventional outer join 15
16
Room2
Room1
JANE
SAM
95 96 96
16
5/11/2017
HR ROOM WHO
------- ---------- ----------
8
9 Room1 JOHN
10
11 Room1 MIKE
12
13
14 HR ROOM WHO
97 98
SQL> select *
2 from timeslots; x "Room 1"
HR
--
8 x "Room 2"
partitioned outer join
9
10
11
12
...
13
14
15 x "Room n"
16
99 100
HR ROOM WHO
--------- ---------- ----------
5
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
101 101 102
17
5/11/2017
103 104
SQL> select empno, ename, hiredate SQL> select empno, ename, hiredate
2 from emp 2 from emp
3 limit 5 3 where rownum <= 5
4 order by hiredate desc; 4 order by hiredate desc;
105 106
SQL> select *
2 from (
3 select empno, ename, hiredate
4 from emp
5 order by hiredate desc
6 )
7 where rownum <= 5;
inline view 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
107 108
18
5/11/2017
109 110
111 112
114
19
5/11/2017
oc01.sql
115 116
117 118
you get other benefits "but what about the next page ?"
oc02.sql
119 120
20
5/11/2017
there
is
no new query
next
page
121 122
123 124
10 select *
11 from first_200
12 where rr between
<= 10 11 and 20
oc03.sql
125 126
21
5/11/2017
127 128
Weblogic
Math.Max(maxDivisor, WinningCombinations[i].Divisor);
}
}
no comments
131 132
22
5/11/2017
133 134
135 136
select emp.*
from emp,
( select trunc(hiredate,'YYYY'), max(empno) empno
from emp
query blocks = where empno > 0
group by trunc(hiredate,'YYYY') ) x,
( select deptno, avg(sal)
from emp
self- documenting SQL group by deptno ) y
where x.empno = emp.empno
and y.deptno = emp.deptno
137 138
23
5/11/2017
?
group by trunc(hiredate,'YYYY') ) x,
( select deptno, avg(sal)
2 | TABLE ACCESS BY INDEX ROWID | EMP | from emp
group by deptno ) y
3 | NESTED LOOPS | | where x.empno = emp.empno
and y.deptno = emp.deptno
4 | VIEW | |
5 | SORT GROUP BY | |
6 | TABLE ACCESS BY INDEX ROWID| EMP | Id | Operation | Name |
----------------------------------------------|
7 | INDEX FULL SCAN | E2 | 0 | SELECT STATEMENT | |
1 | HASH JOIN | |
8 | INDEX RANGE SCAN | E1 | 2 | TABLE ACCESS BY INDEX ROWID | EMP |
9 | VIEW | | 3 |
4 |
NESTED LOOPS
VIEW
|
|
|
|
10 | SORT GROUP BY | | 5 |
6 |
SORT GROUP BY |
TABLE ACCESS BY INDEX ROWID| EMP |
|
139 140
141 142
Session altered.
143 144
24
5/11/2017
************************** *********************************
Query transformations (QT) Number of join permutations tried: 1
************************** *********************************
CBQT: Validity checks passed for 7jpzpr2475cqw. GROUP BY adjustment factor: 1.000000
GROUP BY cardinality: 3.000000, TABLE cardinality: 14.000000
CSE: Sub-expression elimination in query block SEL$1 (#0)
SORT ressource Sort statistics
Sort width: 598 Area size: 1048576 Max Area: 104857600
************************* Degree: 1
Common Subexpression elimination (CSE) Blocks to Sort: 1 Row size: 18 Total Rows: 14
************************* Initial runs: 1 Merge passes: 0 IO Cost / pass: 0
CSE: CSE not performed on query block YR_HIRE (#0). Total IO sort cost: 0 Total CPU sort cost: 14312402
CSE: Sub-expression elimination in query block AV_SAL (#0) Total Temp space used: 0
CSE: CSE not performed on query block AV_SAL (#0). Trying or-Expansion on query block AV_SAL (#3)
Transfer Optimizer annotations for query block AV_SAL (#3)
CSE: CSE not performed on query block SEL$1 (#0).
GROUP BY adjustment factor: 1.000000
Final cost for query block AV_SAL (#3) - All Rows Plan:
*************************** Best join order: 1
Order-by elimination (OBYE) Cost: 4.0029 Degree: 1 Card: 14.0000 Bytes: 98
*************************** Resc: 4.0029 Resc_io: 3.0000 Resc_cpu: 14352069
OBYE: Considering Order-by Elimination from view SEL$1 (#0) Resp: 4.0029 Resp_io: 3.0000 Resc_cpu: 14352069
145 146
SQL> select
2 /*+ QB_NAME(top)
3 INDEX(@yr_hire emp (empno))
4 FULL(@av_sal emp)
5 */ emp.*
6 from emp,
7 ( select /*+ QB_NAME(YR_HIRE) */
8 trunc(hiredate,'YYYY'), max(empno) empno
assist with hints 9
10
from emp
where empno > 0
11 group by trunc(hiredate,'YYYY') ) x,
12 ( select /*+ QB_NAME(AV_SAL) */
13 deptno, avg(sal)
14 from emp
15 group by deptno ) y
16 where x.empno = emp.empno
17 and y.deptno = emp.deptno
147 148
select
/*+ QB_NAME(top)
INDEX(@yr_hire emp (empno))
footnote
FULL(@av_sal emp)
*/
INDEX(emp emp_ix)
150
149
25
5/11/2017
7 totals / subtotals
151 152
EMPNOSQL>
ENAMEselect deptno,SAL DEPTNO
---------- ----------
2 ---------- ----------
sum(sal)
7782 CLARK
3 from emp 2450 10
"Employee salary list, 7839 KING
4 group by deptno
7934 MILLER
5000
1300
10
10
5 order by deptno;
plus department total, ...
7900 JAMES 950 30
DEPTNO SUM(SAL)
plus grand total" 7698----------
BLAKE
7654 MARTIN
SQL>
2850
----------
1250
30
from 30
10 select 8750
sum(sal) emp;
20 10875
SUM(SAL)
30 9400
----------
29025
153 154
rollup
20 10875
30 9400
29025
155 156
26
5/11/2017
157 158
161 162
27
5/11/2017
8 pattern matching
165 166
AML
167 168
28
5/11/2017
169 170
171 172
9
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 )
173 174
29
5/11/2017
175 176
STORES
CUSTOMERS
example
SALES
177 178
sort merge ?
179 180
30
5/11/2017
add indexes ?
rewrite query ?
materialized view ?
result cache ?
oc04.sql
181 182
10 transposition
183 184
185 186
31
5/11/2017
187 188
pivot clause
189 190
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',
or ...
10 'OCT') )
11 order by 1
12 /
32
5/11/2017
193 194
unpivot clause
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
...
195 196
33
5/11/2017
SQL> select
scalar
2 ( select dname
3 from dept
4 where deptno = e.deptno ) dname,
5 decode(empno, 7499,
6 ( select max(sal) from emp ),
scalar queries 7 -1)
8 from anywhere an
9 ( select * from emp
expression could be
10 where sal > 0 ) e
11 where
12 ( select max(hiredate) from emp ) < sysdate
13 /
199 200
34
5/11/2017
205 206
SQL> select
2 empno,
3 ( select dname
4 from dept
SQL> select 5 where deptno = e.deptno ) dname,
2 empno, 6 ( select loc
3 ( select dname, loc, revenue 7 from dept
8 where deptno = e.deptno ) loc,
4 from dept
9 ( select revenue
5 where deptno = e.deptno ) 10 from dept
6 from EMP e; 11 where deptno = e.deptno ) rev
( select dname, loc, revenue 12 from EMP e;
*
EMPNO DNAME LOC REV
ERROR at line 3: ---------- -------------- ------------- ----------
ORA-00913: too many values 7839 ACCOUNTING NEW YORK 10000
7698 SALES CHICAGO 30000
7782 ACCOUNTING NEW YORK 10000
...
207 208
Type created.
209 210
35
5/11/2017
12
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;
first principles
213 214
215 216
36
5/11/2017
recall: WITH
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;
37
5/11/2017
union all
225 226
SQL> with each_level (empno, name, mgr, rlevel) as SQL> with each_level (empno, name) as
2 ( select empno, ename, mgr, 1 rlevel 2 ( select empno, ename from emp
3 from emp 3 where mgr is null
4 where mgr is null 4 union all
5 union all 5 select e.empno,
6 select emp.empno, emp.ename, emp.mgr, rlevel+1 6 each_level.name||'-'||e.ename
7 from emp, each_level 7 from emp e, each_level
8 where emp.mgr = each_level.empno 8 where e.mgr = each_level.empno
9 ) 9 )
10 select * from each_level; 10 select empno, name from each_level;
38
5/11/2017
ERROR:
ORA-32044: cycle detected while executing recursive WITH query
229 230
231 232
SQL> with each_level (empno, name, hiredate, mgr) as SQL> with each_level (empno, name, hiredate, mgr) as
2 ( select empno, ename, hiredate, mgr from emp 2 ( select empno, ename, hiredate, mgr from emp
3 where ename = 'KING' 3 where ename = 'KING'
4 union all 4 union all
5 select e.empno, 5 select e.empno,
6 each_level.name||'-'||e.ename, e.hiredate, e.mgr 6 each_level.name||'-'||e.ename, e.hiredate, e.mgr
7 from emp e, each_level 7 from emp e, each_level
8 where e.mgr = each_level.empno ) 8 where e.mgr = each_level.empno )
9 SEARCH BREADTH FIRST BY HIREDATE SET IDX 9 SEARCH DEPTH FIRST BY HIREDATE SET IDX
10 select name, hiredate, idx from each_level; 10 select name, hiredate, idx from each_level;
39
5/11/2017
iteration / nesting
235 236
237 238
SQL> with
2 tweetised(ind,tweet_txt) as
3 (
IND TWEET_TXT
4 select 1 ind, txt tweet_txt --------- -----------------------------------------------------------------------------------------
1 I caught up with Connor and Maria Colgan today. They have taken over AskTOM for...
5 from messages 2 I caught up with Connor and Maria Colgan today. They have taken over AskTOM for...
6 union all 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 ...
7 select ind+1, replace(tweet_txt,term,handle) 5 I caught up with @connor_mc_d and @sqlmaria today. They have taken over AskTOM for @otndev
8 from tweetised, twitter_handles 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 ...
9 where ind = id
10 )
11 select * from tweetised;
239 240
40
5/11/2017
SQL> with
2 tweetised(ind,tweet_txt) as
3 (
4 select 1 ind, txt tweet_txt
5 from messages
last
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...
241 242
243 244
245 246
41
5/11/2017
247 248
DT VAL VAL
--------- ---------- ----------
02-JAN-11 195 195
03-JAN-11 195
wrap up
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
249 250
251 252
42
5/11/2017
253 254
255 256
258
43
5/11/2017
@connor_mc_d
#MakeDataGreatAgain
44