By expanding our knowledge of SQL facilities, we can let all the boring work be handled via SQL rather than a lot of middle-tier code, and we can get performance benefits as an added bonus. Here are some SQL techniques to solve problems that would otherwise require a lot of complex coding, freeing up your time to focus on the delivery of great applications.
28. 28
"fine-grained to perform a single function"
"Each service is ... minimal, and complete"
https://en.wikipedia.org/wiki/Microservices
select COUNT(*)
from PEOPLE
where GENDER = 'MALE'
multa-granulado para realizar una sola función
Cada servicio es ... mínimo y completo
32. 32
"By abstracting the underlying implementation"
"describes the expected behaviour ... but can have multiple implementations"
https://en.wikipedia.org/wiki/Application_programming_interface
select NAME, STREET_NO, ZIP_CODE
from PEOPLE p,
ADDRESS a
where p.AGE > 50
and p.ADDRESS_ID = a.ADDRESS_ID;
Al abstraer la implementación subyacente
describe el comportamiento esperado ... pero puede tener múltiples implementaciones
37. 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)
45
38. 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 )
46
Ack: Anton Scheffer,
https://technology.amis.nl
41. 49
100%
% of developers that
will need to solve Sudoku
as part of their job
% de desarrolladores que
tendrá que resolver Sudoku
como parte de su trabajo
42. 50
100%
% of developers that need
to get real work done
% de desarrolladores que necesitan
llegar trabajo de verdad hecho
53. "Employee salary list,
plus department total,
plus grand total"
61
"Lista de salario del empleado,
más el total del departamento,
más el gran total "
74. SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_GREAT_FAT_TABLE;
Elapsed: 06:12:34.00
82
75. SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_GREAT_FAT_TABLE;
Elapsed: 06:12:34.00
ERROR at line 1:
ORA-01847: day of month must be between 1 and last day of month
83
84. SQL> insert into MY_TABLE
2 select *
3 from MY_HUGE_GREAT_FAT_TABLE
4 where "not a duplicate"
5 and "datatypes are ok"
6 and "foreign keys are ok"
7 and "check constraints are ok"
92
99. 107
SQL> SELECT hrs.hr, t1.room, t1.who
2 from timeslots hrs
3 left outer join bookings t1
4 on hrs.hr = t1.hr
5 order by 1
HR ROOM WHO
------- ---------- ----------
8 Room2 PETE
9 Room1 JOHN
10
11 Room1 MIKE
12
13
14 Room2 JILL
15 Room2 JANE
16 Room1 SAM
107
119. "data is represented as mathematical n-ary
relations, an n-ary relation being a subset of the
Cartesian product of n domains."
127
"los datos se representan como matemáticos n-ary
relaciones, una n-ary relación siendo un subconjunto
de la Producto cartesiano de n dominios ".
123. "First, get the total salary paid by each department,
then get the average of these totals,
then list those departments above that average"
131
SQL ?
"primero, obtenga el salario total pagado por cada departamento,
entonces obtener el promedio de estos totales,
entonces enumerar esos departamentos por encima de ese promedio "
124. "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),
132
125. "...then get the average of these totals...
6 avg_sal AS ( SELECT AVG(dept_sal) avsal
7 FROM dept_salaries)
133
126. "...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;
134
127. 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;
135
145. "That’s wrong!...surely you know
I wanted it DOWN the page"
153
"Eso está mal! ... seguramente lo sabes
yo lo queria ABAJO la página"
146. SQL> desc SALES_ACROSS
Name Null? Type
----------------------------- -------- -------------
PRODUCT VARCHAR2(20)
Q1 NUMBER
Q2 NUMBER
Q3 NUMBER
Q4 NUMBER
154
150. most of us know about analytics
158
la mayoría de nosotros sabemos sobre análisis
151. SQL> select row_number() OVER ( order by sal )
2 from emp
3 ...
159
https://bit.ly/analytic_sql
152. 160
"Show me lowest salary for each department..."
SQL> select deptno, min(sal)
2 from emp
3 group by deptno;
"...and I need to know who has that lowest salary"
SQL> select deptno, empno, min(sal)
2 from emp
3 group by deptno;
ORA-00979: not a GROUP BY expression
Muéstrame el salario más bajo para cada departamento ...
... y necesito saber quién tiene el salario más bajo
154. SQL> select deptno, min(sal), min(empno)
2 KEEP ( dense_rank FIRST order by sal) empno
3 from emp
4 group by deptno
5 /
DEPTNO MIN(SAL) EMPNO
---------- ---------- ----------
10 1300 7934
20 800 7369
30 950 7900
Emp 7934 has the
lowest salary in dept 10
162
Emp 7934 tiene el salario más
bajo en el departamento 10
163. SQL> select *
2 from customers
3 where cust_name = 'ADAMS';
COUNTRY CREATED CUST_NAME
------------ --------- ------------
AUS 07-NOV-16 ADAMS
164. SQL> select *
2 from customers
3 where upper(cust_name) = 'ADAMS';
COUNTRY CREATED CUST_NAME
------------ --------- ------------
AUS 07-NOV-16 Adams
AUS 07-NOV-16 ADAMS
AUS 07-NOV-16 adams
169. SQL> create index cust_ix
2 on customers ( cust_name );
Index created.
SQL> create index cust_ix2
2 on customers ( upper(cust_name) );
Index created.
178. SQL> create index cust_ix
2 on customers ( cust_name);
Index created.
SQL> set autotrace traceonly explain
SQL> select * from customers
2 where cust_name = 'ADAMS';
-----------------------------------------------------------------
| Id | Operation | Name | Rows |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| CUSTOMERS | 1 |
|* 2 | INDEX RANGE SCAN | CUST_IX | 1 |
-----------------------------------------------------------------
179. 187
"what is so special about that?"
Qué tiene de especial eso?
180. SQL> select * from customers
2 where cust_name = 'ADAMS';
COUNTRY CREATED CUST_NAME
------------ --------- ----------------
AUS 07-NOV-16 Adams
AUS 08-NOV-16 ADAMS
AUS 09-NOV-16 adams
181. 189
binary_ci
SQL> select * from customers
2 where cust_name = 'ADAMS';
COUNTRY CREATED CUST_NAME
------------ --------- ------------
AUS 07-NOV-16 Adams
AUS 08-NOV-16 ADAMS
AUS 09-NOV-16 adams
182. 190
binary_ai
SQL> select * from customers
2 where cust_name = 'ADAMS';
COUNTRY CREATED CUST_NAME
------------ --------- -----------
AUS 07-NOV-16 Adams
AUS 08-NOV-16 ADAMS
AUS 09-NOV-16 adams
AUS 10-NOV-16 adáms
adáms
195. 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
203
196. 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 |
204
197. ?
205
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 |
198. 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
206
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
199. 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
207
203. "if I was paid $3000,
then where would I rank in
each department?"
"si me pagaran $ 3000,
entonces, dónde clasificaría en
cada departamento?"
204. SQL> select
2 deptno,
3 rank(3000) within group
4 ( order by sal ) as ranking
5 from emp
6 group by deptno;
DEPTNO RANKING
---------- ----------
10 2
20 4
30 7
40 2
208. 216
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
209. 217
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
...
210. 218
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
...
211. 219
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
212. 220
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
230. 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
238
231. "I am not impressed"
239
"No estoy impresionado"
232. 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.
240
233. 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, ...
241
243. 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
251
hash outer join ? nested loop ?
STORES first ?
sort merge ?