表emp:

postgresql 自关联有重复数据 plsql关联查询_等值连接

表dept:

postgresql 自关联有重复数据 plsql关联查询_数据_02


表salgrade:

postgresql 自关联有重复数据 plsql关联查询_数据_03

92语法

查询雇员名称和部门对应的名称:

select e.ename,d.dname 
from emp e,dept d 
where e.deptno = d.deptno;

输出:

postgresql 自关联有重复数据 plsql关联查询_左外连接_04

这种关联查询叫做 等值连接,即两个表中包含相同的列名。

查询雇员名称和自己的薪水等级:

select e.ename,sg.grade 
from emp e,salgrade sg 
where e.sal between sg.losal and sg.hisal;

postgresql 自关联有重复数据 plsql关联查询_postgresql 自关联有重复数据_05


两个表中没有相同的列名,但是某一列在另一张表的列的范围内,此为非等值连接。

左外连接/右外连接

–需要将雇员表中的所有数据都进行显示,利用等值连接的话只会把关联到的数据显示,
–没有关联到的数据不会显示,此时需要外连接
–分类:左外连接(把左表的全部数据显示)和右外连接(把右表的全部数据显示)

select * from emp e,dept d where e.deptno = d.deptno;--等值连接
select * from emp e,dept d where e.deptno = d.deptno(+);--左外连接
select * from emp e,dept d where e.deptno(+) = d.deptno;--右外连接

自连接
–自连接,将一张表当成不同的表来看待,自己关联自己
–将雇员和他经理的名称查出来

select e.ename,m.ename from emp e,emp m where e.mgr = m.empno;

笛卡尔积
–当关联多张表,但是不指定连接条件的时候,会进行笛卡尔积,
–关联后的总记录条数为M*n,一般不要使用
select * from emp e,dept d;

99语法

CROSS JOIN
NATURAL JOIN
USING子句
ON子句
LEFT OUTER JOIN
RIGHT OUTER JOIN
FULL OUTER JOIN
Inner join

--cross join 等同于92语法中的笛卡儿积
select * from emp cross join dept;

--natural join  相当于是等值连接,但是注意,不需要写连接条件,会从两张表中找到相同的列做连接
--当两张表中不具有相同的列名的时候,会进行笛卡儿积操作,自然连接跟92语法的自连接没有任何关系
select * from emp e natural join dept d ;
select * from emp e natural join salgrade sg;

--on子句,可以添加任意的连接条件,
--添加连接条件 相当于92语法中的等值连接
select * from emp e join dept d on e.deptno = d.deptno;
--相当于92语法中的非等值连接,
select * from emp e join salgrade sg on e.sal between sg.losal and sg.hisal;

--left outer join ,会把左表中的全部数据正常显示,右表没有对应的数据直接显示空即可
select * from emp e left outer join dept d on e.deptno = d.deptno;
select * from emp e,dept d where e.deptno = d.deptno(+);

--right outer join ,会把右表中的全部数据正常显示,左表中没有对应的记录的话显示空即可
select * from emp e right outer join dept  d on e.deptno = d.deptno;
select * from emp e,dept d where e.deptno(+) = d.deptno;

--full outer join ,相当于左外连接和右外连接的合集
select * from emp e full outer join dept d on e.deptno = d.deptno;

--inner outer join,两张表的连接查询,只会查询出有匹配记录的数据
select * from emp e inner join dept d on e.deptno = d.deptno;
select * from emp e join dept d on e.deptno = d.deptno;

--using,除了可以使用on表示连接条件之外,也可以使用using作为连接条件,此时连接条件的列不再归属于任何一张表
select deptno from emp e join dept d using(deptno);
select e.deptno,d.deptno from emp e join dept d on e.deptno = d.deptno;

--总结:两种语法的SQL语句没有任何限制,再公司中可以随意使用,但是建议使用99语法,不要使用92语法,SQL显得清楚明了

子查询

--1.求平均薪水最高的部门的编号
select deptno,avg(e.sal) from emp e group by deptno;
select max(t.sal) from (select deptno,avg(e.sal) sal from emp e group by deptno) t;

select deptno
  from (select deptno, avg(e.sal) sal from emp e group by deptno)
 where sal =
       (select max(t.sal)
          from (select deptno, avg(e.sal) sal from emp e group by deptno) t);

--2.求部门平均薪水的等级
select deptno,avg(e.sal) from emp e;

select t.deptno, sg.grade
  from salgrade sg
  join (select e.deptno, avg(e.sal) sal from emp e group by e.deptno) t
    on t.sal between sg.losal and sg.hisal;

--3.求部门平均的薪水等级
select e.ename,e.sal,e.deptno,sg.grade 
from salgrade sg,emp e 
where e.sal between sg.losal and sg.hisal;

select avg(t.grade),deptno 
from (select e.ename,e.sal,e.deptno,sg.grade 
from salgrade sg,emp e 
where e.sal between sg.losal and sg.hisal) t
group by deptno;

--4.求薪水最高的前5名雇员
select * from emp e order by e.sal desc;
select * from (select * from emp e order by e.sal desc) where rownum <= 5;

--5.求薪水最高的第6到第10名雇员
select t1.*, rownum rn from (select * from emp e order by e.sal desc) t1 where rownum<=10;

select *
  from (select t1.*, rownum rn
          from (select * from emp e order by e.sal desc) t1
         where rownum <= 10) t
 where t.rn > 5
   and t.rn <= 10;