Oracle 11g xe Tutorial 2

I.Subquery

1.Subquery

Select statement inside a select statement, the result of inner select statement just like a table t, the extern select statement just select data from table t;

# Get the employee whose salary is max
SQL> select ename from emp
  2  where sal = (select max(sal) from emp);

# Get the employees whose salary is greater than average salary
SQL> select ename, sal from emp
  2  where sal > (select avg(sal) from emp);

2.Join

Use join to select data from multiple tables at the same time

  • Self Join
  • Cross Join
  • Outer Join (left/right/full)
# Get the employees whose salary is the max of each department
# wrong example
SQL> select ename, sal, deptno from emp
  2  where sal in (select max(sal) from emp group by deptno);

# right example, use join table
SQL> select ename, sal from emp
  2  join (select deptno, max(sal) max_sal from emp group by deptno) t
  3  on (emp.deptno = t.deptno and emp.sal = t.max_sal);


# Get the manager of employee
# Self join
SQL> select e1.ename employee, e2.ename manager from emp e1, emp e2
  2  where e1.mgr = e2.empno;
SQL> select e1.ename, e2.ename from emp e1 join emp e2
  2  on (e1.mgr = e2.empno);
# Outer join
# left join will show all the record of left table
SQL> select e1.ename, e2.ename from emp e1
  2  left join emp e2
  3  on (e1.mgr = e2.empno);


# Cross Join, get enames and dnames
SQL> select ename, dname from emp, dept;
SQL> select ename, dname from emp
  2  cross join dept;

# Get the employee names and department names
# where
SQL> select ename,dname from emp, dept
  2  where emp.deptno = dept.deptno;
# Join on
SQL> select ename, dname from emp join dept
  2  on (emp.deptno = dept.deptno);
# Join using
SQL> select ename, dname from emp join dept
  2  using (deptno);
# Right outer join, it will show all the records of right table
SQL> select ename, dname from emp
  2  right join dept
  3  on (emp.deptno = dept.deptno);
# Full outer join, it will show all the records of both tables
SQL> select ename,dname from emp
  2  full join dept
  3  on (emp.deptno = dept.deptno);



# Get the salary grade of employees
SQL> select ename, grade from emp e join salgrade s
  2  on (e.sal between s.losal and s.hisal);


# Join three tables
# Get the department name and salary grade of employees
# And the second index of employee name is not A
SQL> select ename, dname, grade from
  2  emp e join dept d
  3  on (e.deptno = d.deptno)
  4  join salgrade s
  5  on (e.sal between s.losal and s.hisal)
  6  where ename not like '_A%';

II. Execise

# Get the employee who has max salary in each department
SQL> select ename, sal from emp
  2  join (select max(sal) max_sal, deptno from emp
  3  group by deptno) t
  4  on (emp.sal = t.max_sal and emp.deptno = t.deptno);

# Get grade of average salary of each department
SQL> select avg_sal, grade, deptno from
  2  (select avg(sal) avg_sal, deptno from emp
  3  group by deptno) t
  4  join salgrade
  5  on (t.avg_sal between salgrade.losal and salgrade.hisal);

# Get average salary grade of each department
SQL> select avg(grade), deptno from
  2  (select sal, grade, deptno from emp
  3  join salgrade s
  4  on (emp.sal between s.losal and s.hisal))
  5  group by deptno;

# Get all managers
SQL> select distinct e2.empno, e2.ename from emp e1
  2  join emp e2 on
  3  (e1.mgr = e2.empno);
SQL> select empno, ename from emp
  2  where empno in (select distinct mgr from emp);

# Get max salary, can not use max() function
# Compare it self.
SQL> select distinct ename, sal from emp where sal not in
  2  (select distinct e1.sal from emp e1
  3  join emp e2 on
  4  (e1.sal < e2.sal));

# Get the number of department who has the max average salary
SQL> select deptno, avg_sal from
  2  (select deptno,avg(sal) avg_sal from emp group by deptno)
  3  where avg_sal =
  4  (select max(avg_sal) from
  5  (select avg(sal) avg_sal from emp group by deptno));

# Get the name of department who has the max average salary
SQL> select dept.deptno, dname, avg_sal from dept
  2  join (select deptno, avg_sal from
  3  (select deptno, avg(sal) avg_sal from emp group by deptno)
  4  where avg_sal =
  5  (select max(avg_sal) from
  6  (select deptno, avg(sal) avg_sal from emp group by deptno)))
  7  t on (t.deptno = dept.deptno);
# Use Embeded Group Function (two level maximum)
SQL> select dept.deptno, dname, avg_sal from dept
  2  join (select deptno, avg_sal from
  3  (select deptno, avg(sal) avg_sal from emp group by deptno)
  4  where avg_sal =
  5  (select max(avg(sal)) from emp group by deptno)) t
  6  on (t.deptno = dept.deptno);


# Get the name of department who has the min grade of average salary
SQL> select deptno, dname, avg_sal, grade from
  2  (select dept.deptno, dept.dname, avg_sal from dept
  3  join (select deptno, avg_sal from
  4  (select deptno, avg(sal) avg_sal from emp group by deptno)
  5  where avg_sal =
  6  (select min(avg_sal) from
  7  (select deptno, avg(sal) avg_sal from emp group by deptno)))
  8  t on (t.deptno = dept.deptno))
  9  t2 join salgrade s on
 10  (t2.avg_sal between s.losal and s.hisal);
# Embeded Group Function
SQL> select deptno, dname, avg_sal, grade from
  2  (select dept.deptno, dept.dname, avg_sal from dept
  3  join (select deptno, avg_sal from
  4    (select deptno,avg(sal) avg_sal from emp group by deptno)
  5  where avg_sal =
  6  (select min(avg(sal)) from emp group by deptno))
  7  t on (t.deptno = dept.deptno))
  8  t2 join salgrade s on
  9  (t2.avg_sal between s.losal and s.hisal);


# Get the manager whose salary is greater than the max salary of normal employees
# Normal employees means they are not managers
SQL> select ename, sal from emp
  2  where empno in (select distinct mgr from emp where mgr is not null)
  3  and sal >
  4  (select max(sal) from emp where empno not in
  5  (select distinct mgr from emp where mgr is not null));

II. View

Create view to repalce some complexe subquery, in fact it’s a virtual table.

1. View example

To create a view: create view v$view_name as subquery

SQL> create view v$dept_avg_sal_info as
  2  select deptno, grade, avg_sal from
  3  (select deptno, avg(sal) avg_sal from emp group by deptno) t
  4  join salgrade s on (t.avg_sal between s.losal and s.hisal);
create view v$dept_avg_sal_info as
            *
ERROR at line 1:
ORA-01031: insufficient privileges

Here you will see it returns an error, that’s because scott user doesn’t has privileges to create a view, so we need to grant privileges:

SQL> conn sys as sysdba
Enter password:
Connected.
SQL> grant create table, create view to scott;

Grant succeeded.

Now scott account can create view ang table.

2. Use view

SQL> conn scott/tiger
Connected.
SQL> create view v$dept_avg_sal_info as
  2  select deptno, grade, avg_sal from
  3  (select deptno, avg(sal) avg_sal from emp group by deptno) t
  4  join salgrade s on (t.avg_sal between s.losal and s.hisal);

View created.

SQL> select * from v$dept_avg_sal_info;

# Get the name of department who has the min grade of average salary
SQL> select t1.deptno, dname, avg_sal, grade from
  2  v$dept_avg_sal_info t1 join dept on
  3  (t1.deptno = dept.deptno)
  4  where t1.grade =
  5  (select min(grade) from v$dept_avg_sal_info)
  6  ;

Share this on