$
\begin{aligned}
(2 + 4) \times 3 &= 6 \times 3 &= 18 \
&=(2 + 2 + 2) \times 3\
&=2 \times 3 + 4 \times 3 \
&=2 \times 3 + (2 + 2) \times 3 \
\end{aligned}
$
查询优化器完成具体查询的优化
// 错误的
select empname, salary
from employees
where status != 'EXECUTIVE'
and rownum <= 5
order by salary desc
// 正确的
select *
from (select empname, salary
from employees
where status != 'EXECUTIVE'
order by salary desc)
where rownum <= 5
select
from t1
inner join t2
on t1.join1 = t2.join2
where ...
# 如果存在t1.c2>100这个条件放哪里?
select * from p
where pname like '%size'
and ptype = 'NUMBER'
and int(pvalue) > 1000
select distinct c.custname
from customers c
join orders o
on o.custid = c.custid
join orderdetail od
on od.ordid = o.ordid
join articles a
on a.artid = od.artid
where c.city = 'Nanjing'
and a.artname = 'BMW'
and o.ordered >= somefunc /*函数,返回六个月前的具体日期*/
select distinct c.custname
from customers c,
orders o,
orderdetail od,
articles a
where c.city = 'Nanjing'
and c.custid = o.custid
and o.ordid = od.ordid
and od.artid = a.artid
and a.artname = 'BMW'
and o.ordered >= somefunc
select c.custname
from customers c
where c.city = 'Nanjing'
and exists (select null
from orders o,
orderdetail od,
articles a
where a.artname = 'BMW'
and a.artid = od.artid
and od.ordid = o.ordid
and o.custid = c.custid /* Exists嵌套子查询和外层select关系非常密切 */
and o.ordered >= somefunc )
select custname
from customers
where city = 'Nanjing'
and custid in (select o.custid
from orders o,
orderdetail od,
articles a
where a.artname = 'BMW'
and a.artid = od.artid
and od.ordid = o.ordid
and o.ordered >= somefunc)
select custname
from customers
where city = 'NanJing'
and custid in
(select o.custid
from orders o
where o.ordered >= somefunc
and exists (select null
from orderdetail od,
articles a
where a.artname = 'BMW'
and a.artid = od.artid
and od.ordid = o.ordid))
select custname
from customers
where city = 'NanJing'
and custid in
(select custid
from orders
where ordered >= somefunc
and ordid in (select od.ordid
from orderdetail od,
articles a
where a.artname = 'BMW'
and a.artid = od.artid)
select custname
from customers
where city = 'Nanjing'
and custid in
(select o.custid
from orders o,
(select distinct od.ordid
from orderdetail od,
articles a
where a.artname = 'BMW'
and a.artid = od.artid) x
where o.ordered >= somefunc
and x.ordid = o.ordid)
# 1
SELECT DISTINCT film.film_id
FROM sakila.film
INNER JOIN sakila.film_actor USING(film_id);
# 2
SELECT film_id
FROM sakila.film
WHERE EXISTS(
SELECT * FROM sakila.film_actor
WHERE film.film_id = film_actor.film_id);
(1) a = 1000
(2) a = 500 + 500 CBO只能将(2)自动转化成(1),无法改变(3),这是f()
(3) a – 500 = 500 在全表扫描的时候,(2)(1)是一个比较操作,(3)是一个减法操作
create table t as select x from dba_objects;
insert into t select * from t;
/* 1 √ */
set time on
select count(*) from t
where cteated>=to_date('2019-04-20 00:00:00','yyyy-mm-dd hh24:mi:ss')
and created<to_date('2019-04-21 00:00:00','yyyy-mm-dd hh24:mi:ss')
group by owner;
/* 2 × */
select count(*) from t
where to_char(created,'yyyy-mm-dd')='2019-04-20'
group by owner;
/* 3 × */
select count(*) from t
where to_char(created,'yyyy-mm-dd hh24:mi:ss')>='2019-04-20 00:00:00'
and to_char(created,,'yyyy-mm-dd hh24:mi:ss')<= '2019-04-20 23:59:59'
group by owner
Select …
From A, B, C , D, E1
Where (condition on E1)
and (join and other conditions)
Union
Select …
From A,B,C,D,E2
Where (condition on E2)
and (join and other conditions)
/* 更新为 */
Select…
From A,B,C,D,
(select …
from E1
where (condition on E1)
union
select…
from E2
where (condition on E2)
) E
Where (joins and other conditions)
Select payment from salary where rank=
(select rank from ranks where title=
(select title from jobs where employee = '…'))
/* 修改为 */
Select payment from salary, ranks,jobs
Where salary.rank = ranks.rank
And ranks.title = jobs.title
And jobs.employee = '…'
Select salary.ranks salary.payment from salary
Where rank NOT IN (select rank from ranks)
/* 修改为 */
Select salary.ranks salary.payment
From salary
LEFT OUTER JOIN ON(salary.rank = ranks.rank)
Where ranks.rank IS NULL
select c.custname, o.ordid, os.status, os.statusdate
from customers c,
orders o,
orderstatus os
where o.ordid = os.ordid
and not exists (select null
from orderstatus os2
where os2.status = 'COMPLETE'
and os2.ordid = o.ordid)
and os.statusdate = (select max(statusdate)
from orderstatus os3
where os3.ordid = o.ordid)
and o.custid = c.custid
and (o.ordid, os.statusdate)
=
(select ordid, max(statusdate)
from orderstatus
group by ordid)
select c.custname, o.ordid, os.status, os.statusdate
from customers c,
orders o,
orderstatus os,
(select ordid, max(statusdate) laststatusdate
from orderstatus
group by ordid) x
where o.ordid = os.ordid
and not exists (select null
from orderstatus os2
where os2.status = 'COMPLETE'
and os2.ordid = o.ordid)
and os.statusdate = x.laststatusdate
and os.ordid = x.ordid
and o.custid = c.custid
select c.custname, o.ordid, os.status, os.statusdate
from customers c,
orders o,
orderstatus os,
(select ordid, max(statusdate) laststatusdate
from orderstatus
group by ordid) x
where o.ordid = os.ordid
and os.statusdate = x.laststatusdate
and os.ordid = x.ordid
and os.status != 'COMPLETE'
and o.custid = c.custid
Select custid, ordered, totalitems
From orders o1
Where o1.ordered = (
select max(ordered)
from orders o2
where o1.custid = o2.custid)
1 select substr(e.ename,iter.pos,1) as C
2 from (select ename from emp where ename = 'KING') e,
3 (select id as pos from t10) iter
4 where iter.pos <= length(e.ename)
1 select 'g''day mate' qmarks from t1 union all
2 select 'beavers'' teeth' from t1 union all
3 select '''' from t1
1 select (length('10,CLARK,MANAGER')-
2 length(replace('10,CLARK,MANAGER',',','')))/length(',')
3 as cnt
4 from t1
select
(length('HELLO HELLO')-
length(replace('HELLO HELLO','LL','')))/length('LL')
as correct_cnt,
(length('HELLO HELLO')-
length(replace('HELLO HELLO','LL',''))) as incorrect_cnt
from t1
/* Oracle and PostgreSQL */
1 select ename,
2 replace(translate(ename,'AEIOU','aaaaa'),'a')
3 as stripped1,
4 sal,
5 replace(sal,0,'') as stripped2
6 from emp
/* MySQL and SQL Server */
1 select ename,
2 replace(
3 replace(
4 replace(
5 replace(
6 replace(ename,'A',''),'E',''),'I',''),'O',''),'U','')
7 as stripped1,
8 sal,
9 replace(sal,0,'') stripped2
10 from emp
/* Oracle */
1 select replace(
2 translate(data,'0123456789','0000000000'),'0') ename,
3 to_number(
5 replace(
6 translate(lower(data),
7 'abcdefghijklmnopqrstuvwxyz',
8 rpad('z',26,'z')),'z')) sal
9 from (
10 select ename||sal data
11 from emp
12 )
/* MySQL */
1 select data
2 from V
3 where data regexp '[^0-9a-zA-Z]' = 0
/* Oracle */
1 select data
2 from V
3 where translate(lower(data), '0123456789abcdefghijklmnopqrstuvwxyz',rpad('a',36,'a'))
4 = rpad('a',length(data),'a')
/* MySQL */
1 select case
2 when cnt = 2 then
3 trim(trailing '.' from
4 concat_ws('.',
5 substr(substring_index(name,' ',1),1,1),
6 substr(name,
7 length(substring_index(name,' ',1))+2,1),
8 substr(substring_index(name,' ',-1),1,1),
9 '.'))
10 else
11 trim(trailing '.' from
12 concat_ws('.',
13 substr(substring_index(name,' ',1),1,1),
14 substr(substring_index(name,' ',-1),1,1)
15 ))
16 end as initials
17 from (
18 select name,length(name)-length(replace(name,' ','')) as cnt
19 from (
20 select replace('Stewie Griffin','.','') as name from t1
21 ) y
22 ) x
/* Oracle and PostgreSQL */
1 select replace(
2 replace(
3 translate(replace('Stewie Griffin', '.', ''),
4 'abcdefghijklmnopqrstuvwxyz',
5 rpad('#',26,'#') ), '#','' ),' ','.' ) ||'.'
6 from t1
1 select avg(sal) as avg_sal
2 from emp
AVG_SAL
----------
2073.21429
create table t2(sal integer)
insert into t2 values (10)
insert into t2 values (20)
insert into t2 values (null)
select avg(sal)
from t2
AVG(SAL)
----------
15
select avg(coalesce(sal,0))
from t2
AVG(COALESCE(SAL,0))
--------------------
10
1 select deptno, avg(sal) as avg_sal
2 from emp
3 group by deptno
DEPTNO AVG_SAL
----------- ----------------
10 2916.66667
20 2175
30 1566.66667
1 select avg(sal)
2 from emp
3 group by deptno
AVG(SAL)
----------------
2916.66667
2175
1566.66667
1 select min(sal) as min_sal, max(sal) as max_sal
2 from emp
MIN_SAL MAX_SAL
------------ --------------
800 5000
1 select deptno, min(sal) as min_sal, max(sal) as max_sal
2 from emp
3 group by deptno
DEPTNO MIN_SAL MAX_SAL
------------ -------------- ------------
10 1300 5000
20 800 3000
30 950 2850
1 select sum(sal)
2 from emp
SUM(SAL)
----------
29025
1 select deptno, sum(sal) as total_for_dept
2 from emp
3 group by deptno
DEPTNO TOTAL_FOR_DEPT
---------- --------------
10 8750
20 10875
30 9400
1 select count(*)
2 from emp
COUNT(*)
--------
14
1 select deptno, count(*)
2 from emp
3 group by deptno
DEPTNO COUNT(*)
---------- ----------
10 3
20 5
30 6
select count(comm)
from emp
COUNT(COMM)
-----------
4
/* Oracle and DB2(MySQL已经支持了) */
1 select ename, sal,
2 sum(sal) over (order by sal,empno)
3 as running_total
4 from emp
5 order by 2
/* MySQL and PostgreSQL and SQL Server */
1 select e.ename, e.sal,
2 (select sum(d.sal) from emp d
3 where d.empno <= e.empno) as running_total
4 from emp e
5 order by 3
select sal
from emp
where deptno = 20
order by sal
SAL
----------
800
1100
2975
3000
3000
/* Oracle */
1 select max(sal)
2 keep(dense_rank first order by cnt desc) sal
3 from (
4 select sal, count(*) cnt
5 from emp
6 where deptno=20
7 group by sal
8 )
/* MySQL and PostgreSQL */
1 select sal
2 from emp
3 where deptno = 20
4 group by sal
5 having count(*) >= all ( select count(*)
6 from emp
7 where deptno = 20
8 group by sal )
select sal
from emp
where deptno = 20
order by sal
SAL
----------
800
1100
2975
3000
3000
/* MySQL and PostgreSQL */
1 select avg(sal)
2 from (
3 select e.sal
4 from emp e, emp d
5 where e.deptno = d.deptno
6 and e.deptno = 20
7 group by e.sal
8 having sum(case when e.sal = d.sal then 1 else 0 end)
9 >= abs(sum(sign(e.sal - d.sal)))
10 ) x
/* Oracle */
1 select median(sal)
2 from emp
3 where deptno=20
/* MySQL and PostgreSQL */
1 select (sum(
2 case when deptno = 10 then sal end)/sum(sal)
3 )*100 as pct
4 from emp
/* DB2, Oracle, and SQL Server */
1 select distinct (d10/total)*100 as pct
2 from (
3 select deptno,
4 sum(sal)over( ) total,
5 sum(sal)over(partition by deptno) d10
6 from emp
7 ) x
8 where deptno=10
/* MySQL and PostgreSQL */
1 select avg(sal)
2 from emp
3 where sal not in (
4 (select min(sal) from emp),
5 (select max(sal) from emp)
6 )
/* DB2, Oracle, and SQL Server
*/
1 select avg(sal)
2 from (
3 select sal, min(sal)over() min_sal, max(sal)over() max_sal
4 from emp
5 ) x
6 where sal not in (min_sal,max_sal)
create view V (id,amt,trx)
as
select 1, 100, 'PR' from t1 union all
select 2, 100, 'PR' from t1 union all
select 3, 50, 'PY' from t1 union all
select 4, 100, 'PR' from t1 union all
select 5, 200, 'PY' from t1 union all
select 6, 50, 'PY' from t1
/* DB2 and Oracle */
1 select case when trx = 'PY'
2 then 'PAYMENT'
3 else 'PURCHASE'
4 end trx_type,
5 amt,
6 sum(
7 case when trx = 'PY'
8 then -amt else amt
9 end
10 ) over (order by id,amt) as balance
11 from V
/* MySQL, PostgreSQL, and SQL Server */
1 select case when v1.trx = 'PY'
2 then 'PAYMENT'
3 else 'PURCHASE'
4 end as trx_type,
5 v1.amt,
6 (select sum(
7 case when v2.trx = 'PY'
8 then -v2.amt else v2.amt
9 end
10 )
11 from V v2
12 where v2.id <= v1.id) as balance
13 from V v1
/* Oracle */
1 select hiredate-5 as hd_minus_5D,
2 hiredate+5 as hd_plus_5D,
3 add_months(hiredate,-5) as hd_minus_5M,
4 add_months(hiredate,5) as hd_plus_5M,
5 add_months(hiredate,-5*12) as hd_minus_5Y,
6 add_months(hiredate,5*12) as hd_plus_5Y
7 from emp
8 where deptno = 10
/* MySQL */
1 select hiredate - interval 5 day as hd_minus_5D,
2 hiredate + interval 5 day as hd_plus_5D,
3 hiredate - interval 5 month as hd_minus_5M,
4 hiredate + interval 5 month as hd_plus_5M,
5 hiredate - interval 5 year as hd_minus_5Y,
6 hiredate + interval 5 year as hd_plus_5Y
7 from emp
8 where deptno=10
/* date_add是函数 */
1 select date_add(hiredate,interval -5 day) as hd_minus_5D,
2 date_add(hiredate,interval 5 day) as hd_plus_5D,
3 date_add(hiredate,interval -5 month) as hd_minus_5M,
4 date_add(hiredate,interval 5 month) as hd_plus_5M,
5 date_add(hiredate,interval -5 year) as hd_minus_5Y,
6 date_add(hiredate,interval 5 year) as hd_plus_5DY
7 from emp
8 where deptno=10
/* Oracle and PostgreSQL */
1 select ward_hd - allen_hd
2 from (
3 select hiredate as ward_hd
4 from emp
5 where ename = 'WARD'
6 ) x,
7 (
8 select hiredate as allen_hd
9 from emp
10 where ename = 'ALLEN'
11 ) y
/* MySQL and SQL Server 第一个参数要比较晚,第二个参数要比较早*/
1 select datediff(ward_hd,allen_hd)
2 from (
3 select hiredate as ward_hd
4 from emp
5 where ename = 'WARD'
6 ) x,
7 (
8 select hiredate as allen_hd
9 from emp
10 where ename = 'ALLEN'
11 ) y
/* MySQL 使用数据透视表(t500)表只有id,从1-500,先找到有多少天,再排除掉周六日,注意id要先减1再加1 */
1 select sum(case when date_format(
2 date_add(jones_hd,
3 interval t500.id-1 DAY),'%a')
4 in ( 'Sat','Sun' )
5 then 0 else 1
6 end) as days
7 from (
8 select max(case when ename = 'BLAKE'
9 then hiredate
10 end) as blake_hd,
11 max(case when ename = 'JONES'
12 then hiredate
13 end) as jones_hd
14 from emp
15 where ename in ( 'BLAKE','JONES' )
16 ) x,
17 t500
18 where t500.id <= datediff(blake_hd,jones_hd)+1
/* Oracle */
Oracle
1 select sum(case when to_char(jones_hd+t500.id-1,'DY')
2 in ( 'SAT','SUN' )
3 then 0 else 1
4 end) as days
5 from (
6 select max(case when ename = 'BLAKE'
7 then hiredate
8 end) as blake_hd,
9 max(case when ename = 'JONES'
10 then hiredate
11 end) as jones_hd
12 from emp
13 where ename in ( 'BLAKE','JONES' )
14 ) x,
15 t500
16 where t500.id <= blake_hd-jones_hd+1
/* MySQL */
1 select x.*,
2 datediff(x.next_hd, x.hiredate) diff
3 from (
4 select e.deptno, e.ename, e.hiredate,
5 (select min(d.hiredate) from emp d
6 where d.hiredate > e.hiredate) next_hd
7 from emp e
8 where e.deptno = 10
9 ) x
/* Oracle 检查2月的最后一天 */
1 select to_char(
2 last_day(add_months(trunc(sysdate,'y'),1)),
3 'DD')
4 from t1
/* 第一步,得到年的第一天 */
select trunc(sysdate,'y')
from t1
-----------
01-JAN-2020
/* 第二步,加一个月 */
select add_months(trunc(sysdate,'y'),1) dy
from t1
-----------
01-FEB-2020
/* 第三步,找到最后一天 */
select last_day(add_months(trunc(sysdate,'y'),1)) dy
from t1
-----------
29-FEB-2020
/* MySQL */
1 select day(
2 last_day(
3 date_add(
4 date_add(
5 date_add(current_date,
6 interval -dayofyear(current_date) day),
7 interval 1 day),
8 interval 1 month))) dy
9 from t1
期末考试有可能会考
/* Oracle */
1 select add_months(trunc(sysdate,'y'),12) - trunc(sysdate,'y')
2 from dual
/* MySQL */
1 select datediff((curr_year + interval 1 year),curr_year)
2 from (
3 select adddate(current_date,-dayofyear(current_date)+1) curr_year
4 from t1
5 ) x
/* Oracle */
1 select next_day(trunc(sysdate,'mm')-1,'MONDAY') first_monday,
2 next_day(last_day(trunc(sysdate,'mm'))-7,'MONDAY') last_monday
3 from dual
/* MySQL 先检查当前月份的第一天,然后从第一个星期一推导下一个星期一 */
1 select first_monday,
2 case month(adddate(first_monday,28))
3 when mth then adddate(first_monday,28)
4 else adddate(first_monday,21)
5 end last_monday
6 from (
7 select case sign(dayofweek(dy)-2)
8 when 0 then dy
9 when -1 then adddate(dy,abs(dayofweek(dy)-2))
10 when 1 then adddate(dy,(7-(dayofweek(dy)-2)))
11 end first_monday,
12 mth
13 from (
14 select adddate(adddate(current_date,-day(current_date)),1) dy,
15 month(current_date) mth
16 from t1
17 ) x
18 ) y
/* MySQL */
1 select ename
2 from emp
3 where monthname(hiredate) in ('February','December')
4 or dayname(hiredate) = 'Tuesday'
/* Oracle */
1 select ename
2 from emp
3 where rtrim(to_char(hiredate,'month')) in ('february','december')
4 or rtrim(to_char(hiredate,'day')) = 'tuesday'
select * from emp_project
/* MySQL */
1 select a.empno,a.ename,
2 concat('project ',b.proj_id,
3 ' overlaps project ',a.proj_id) as msg
4 from emp_project a,
5 emp_project b
6 where a.empno = b.empno
7 and b.proj_start >= a.proj_start
8 and b.proj_start <= a.proj_end
9 and a.proj_id != b.proj_id
/* Oracle, PostgreSQL, and DB2 */
1 select a.empno,a.ename,
2 'project '||b.proj_id||
3 ' overlaps project '||a.proj_id as msg
4 from emp_project a,
5 emp_project b
6 where a.empno = b.empno
7 and b.proj_start >= a.proj_start
8 and b.proj_start <= a.proj_end
9 and a.proj_id != b.proj_id
1 select ename as ename_and_dname, deptno
2 from emp
3 where deptno = 10
4 union all
5 select '----------', null
6 from t1
7 union all
8 select dname, deptno
9 from dept
/* × */
select deptno
from dept
union all
select ename
from emp
/* × */
select deptno, dname
from dept
union
select deptno
from emp
/* 重复记录Union ALL纳入,union去掉重复行是排序删除重复行,所以大规模结果集会出现问题 */
select deptno
from emp
union
select deptno
from dept
DEPTNO
---------
10
20
30
40
select distinct deptno
from (
select deptno
from emp
union all
select deptno
from dept
)
DEPTNO
---------
10
20
30
40
/* Oracle 要求类型和个数相同,不返回重复值,空值没有问题*/
1 select deptno from dept
2 minus
3 select deptno from emp
/* MySQL and SQL Server MySQL要使用子查询 */
1 select deptno
2 from dept
3 where deptno not in (select deptno from emp)
/* DB2 and PostgreSQL */
1 select deptno from dept
2 except
3 select deptno from emp
/* 如果DEPTNO不是主键 */
1 select distinct deptno
2 from dept
3 where deptno not in (select deptno from emp)
select deptno
from dept
where deptno in ( 10,50, null)
DEPTNO
-------
10
select deptno
from dept
where (deptno=10 or deptno=50 or deptno=null)
DEPTNO
-------
10
select deptno
from dept
where deptno not in ( 10,50,null )
(no rows)
select deptno
from dept
where not (deptno=10 or deptno=50 or deptno=null)
(no rows)
(false or false or null)
(false or null)
null
DEPTNO DNAME LOC
---------- ----------------- -------------
40 OPERATIONS BOSTON
/* DB2, MySQL, PostgreSQL, SQL Server, Oracle */
1 select d.*
2 from dept d left outer join emp e
3 on (d.deptno = e.deptno)
4 where e.deptno is null
/* Oracle */
1 select d.*
2 from dept d, emp e
3 where d.deptno = e.deptno (+)
4 and e.deptno is null
select e.ename, e.deptno as emp_deptno, d.*
from dept d left join emp e
on (d.deptno = e.deptno)
create view V
as
select * from emp where deptno != 10
union all
select * from emp where ename = 'WARD'
/* Oracle */
1 (
2 select empno,ename,job,mgr,hiredate,sal,comm,deptno,
3 count(*) as cnt
4 from V
5 group by empno,ename,job,mgr,hiredate,sal,comm,deptno
6 minus
7 select empno,ename,job,mgr,hiredate,sal,comm,deptno,
8 count(*) as cnt
9 from emp
10 group by empno,ename,job,mgr,hiredate,sal,comm,deptno
11 )
12 union all
13 (
14 select empno,ename,job,mgr,hiredate,sal,comm,deptno,
15 count(*) as cnt
16 from emp
17 group by empno,ename,job,mgr,hiredate,sal,comm,deptno
18 minus
19 select empno,ename,job,mgr,hiredate,sal,comm,deptno,
20 count(*) as cnt
21 from v
22 group by empno,ename,job,mgr,hiredate,sal,comm,deptno
23 )
/* MySQL and SQL Server */
1 select *
2 from (
3 select e.empno,e.ename,e.job,e.mgr,e.hiredate,
4 e.sal,e.comm,e.deptno, count(*) as cnt
5 from emp e
6 group by empno,ename,job,mgr,hiredate,
7 sal,comm,deptno
8 ) e
9 where not exists (
10 select null
11 from (
12 select v.empno,v.ename,v.job,v.mgr,v.hiredate,
13 v.sal,v.comm,v.deptno, count(*) as cnt
14 from v
15 group by empno,ename,job,mgr,hiredate,
16 sal,comm,deptno
17 ) v
18 where v.empno = e.empno
19 and v.ename = e.ename
20 and v.job = e.job
21 and v.mgr = e.mgr
22 and v.hiredate = e.hiredate
23 and v.sal = e.sal
24 and v.deptno = e.deptno
25 and v.cnt = e.cnt
26 and coalesce(v.comm,0) = coalesce(e.comm,0)
27 )
28 union all
29 select *
30 from (
31 select v.empno,v.ename,v.job,v.mgr,v.hiredate,
32 v.sal,v.comm,v.deptno, count(*) as cnt
33 from v
34 group by empno,ename,job,mgr,hiredate,
35 sal,comm,deptno
36 ) v
37 where not exists (
38 select null
39 from (
40 select e.empno,e.ename,e.job,e.mgr,e.hiredate,
41 e.sal,e.comm,e.deptno, count(*) as cnt
42 from emp e
43 group by empno,ename,job,mgr,hiredate,
44 sal,comm,deptno
45 ) e
46 where v.empno = e.empno
47 and v.ename = e.ename
48 and v.job = e.job
49 and v.mgr = e.mgr
50 and v.hiredate = e.hiredate
51 and v.sal = e.sal
52 and v.deptno = e.deptno
53 and v.cnt = e.cnt
54 and coalesce(v.comm,0) = coalesce(e.comm,0))
/* FULL OUTER JOIN */
1 select d.deptno,d.dname,e.ename
2 from dept d full outer join emp e
3 on (d.deptno=e.deptno)
/* union */
1 select d.deptno,d.dname,e.ename
2 from dept d right outer join emp e
3 on (d.deptno=e.deptno)
4 union
5 select d.deptno,d.dname,e.ename
6 from dept d left outer join emp e
7 on (d.deptno=e.deptno)
select * from emp_bonus
select e.empno,
e.ename,
e.sal,
e.deptno,
e.sal*case when eb.type = 1 then .1
when eb.type = 2 then .2
else .3
end as bonus
from emp e, emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
select deptno,
sum(sal) as total_sal,
sum(bonus) as total_bonus
from (
select e.empno,
e.ename,
e.sal,
e.deptno,
e.sal*case when eb.type = 1 then .1
when eb.type = 2 then .2
else .3
end as bonus
from emp e, emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
) x
group by deptno
DEPTNO TOTAL_SAL TOTAL_BONUS
------ ------ ------
10 10050 2135
/* 单独计算一下金额,问题?部分员工被计算了2次 */
select sum(sal) from emp where deptno=10
SUM(SAL)
----------
8750
select e.ename,
e.sal
from emp e, emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
ENAME SAL
---------- ----------
CLARK 2450
KING 5000
MILLER 1300
MILLER 1300
/* Perform a sum of only the DISTINCT salaries: 不得不使用distinct*/
1 select deptno,
2 sum(distinct sal) as total_sal,
3 sum(bonus) as total_bonus
4 from (
5 select e.empno,
6 e.ename,
7 e.sal,
8 e.deptno,
9 e.sal*case when eb.type = 1 then .1
10 when eb.type = 2 then .2
11 else .3
12 end as bonus
13 from emp e, emp_bonus eb
14 where e.empno = eb.empno
15 and e.deptno = 10
16 ) x
17 group by deptno
select * from emp_bonus
/* 错误的示范 少算 */
select deptno,
sum(sal) as total_sal,
sum(bonus) as total_bonus
from (
select e.empno,
e.ename,
e.sal,
e.deptno,
e.sal*case when eb.type = 1 then .1
when eb.type = 2 then .2
else .3 end as bonus
from emp e, emp_bonus eb
where e.empno = eb.empno
and e.deptno = 10
)
group by deptno
DEPTNO TOTAL_SAL TOTAL_BONUS
------ ---------- -----------
10 2600 390