oracle高级查询(学习Oracle第五天)

一、实体实体之间的关联关系


1.OneToOne:  一对一
             一个公民对应一个身份证号
         一个学生对应一个学号
         一个人对应一个DNA
         ...

2.ManyToOne: 多对一
             一个人有多张银行卡
         一个人有多个QQ号
         一个人有多个电话号码
         ...

3.ManyToMany:多对多
             一名学生有多个老师
         一个老师教多个学生
         --------------------
         一名学生学多门课
         一门课被多名学生学

----------------------------------------------
世界是由物质组成的,物质是运动变化的。物质和物质有联系的。
世界上永远变化的就是变化。




二、连接(Join)是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。

多表连接查询是使用SQL的基本操作,但连接的方式却有多种,熟练使用这些连接方式能够简化SQL
语句,提高数据库运行效率。
    
    SQL的连接分为以下七种情况:
    INNER JOIN : 内连接也称等值连接
    LEFT JOIN 或者 LEFT OUTER JOIN :左连接
    LEFT JOIN 的特殊情况:只查询左连接时不满足条件的记录
    RIGHT JOIN 或者 RIGHT JOIN :右连接
    RIGHT JOIN 的特殊情况:只查询右连接时不满足的条件的记录
    FULL JOIN 或者 FULL OUTER JOIN:全连接
    CROSS JOIN:交叉查询,等同于与笛卡尔积

oracle高级查询(学习Oracle第五天)

--内连接也称等值连接
select stu.sid , sname , c.cid , cname , score from 
score s , students stu , course c
where s.sid = stu.sid and s.cid = c.cid;

--测试笛卡尔积
select stu.sid , sname , c.cid , cname ,score from
score s , students stu , course c;

----内连接也称等值连接
--内连接
select stu.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s 
inner join students stu on s.sid = stu.sid;

--等值连接
select stu.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s , students stu 
where s.sid = stu.sid;

--左连接
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
left join students stu on s.sid = stu.sid;

--左连接特殊情况
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
left join students stu on s.sid = stu.sid
where stu.sid is null;

--右连接
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
right join students stu on s.sid = stu.sid;

--右连接特殊情况
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
left join students stu on s.sid = stu.sid
where s.sid is null;

--全连接
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
full outer join students stu on s.sid = stu.sid;

--全连接的特殊情况
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
full outer join students stu on s.sid = stu.sid
where stu.sid is null or s.sid is null;

--交叉查询,等同于与笛卡尔积
select s.sid as 学生编号 , sname as 姓名 , s.cid as 课程编号 , score as 分数 from
score s
cross join students stu;



三、子查询

1.子查询是嵌入到另外一个SELECT语句中的一个SELECT语句。通过使用子查询,
可以使用简单的语句组成强大的语句。当需要从表中选择行,而选择条件却取
决于该表自身中的数据时,子查询非常有用。
2.子查询主要分为以下两种基本类型:
  (1)单行子查询
  (2)多行子查询
3.另外,还有以下3种类型
  (1)多列子查询
  (2)关联子查询
  (3)嵌套子查询


--where中使用子查询
--查询大于公司平均工资的员工资料
select * from emp where sal > (select avg(sal) from emp);

--having中使用子查询
----查询大于公司平均工资的部门平均工资
select avg(sal) from emp group by deptno having avg(sal) > (select avg(sal) from emp);

--多行子查询 IN ANY ALL
--找出除了最高工资之外的所有员工 
select * from emp where sal < ANY(select sal from emp);
--找出除了最高工资的员工
select * from emp where sal >= ALL(select sal from emp);

--多列子查询
--找出每个部门中工资最低的员工资料
select * from emp
where sal 
IN (select MIN(sal) from emp group by deptno);

--关联子查询
--查询出每个部门中,高出本部门平均工资的员工的雇员号和姓名
select empno , ename ,sal , deptno from emp emouter
where sal > (select avg(sal) from emp eminner where emouter.deptno = eminner.deptno);

--可以使用EXISTS操作符检查是否存在由子查询返回的行
--查询emp表中可以管理别的员工的员工
select * from emp emouter 
where exists (select * from emp eminner where emouter.empno = eminner.mgr);

select * from emp;

--关联子查询中使用NOT EXISTS
--查询不在部门10的员工信息
select * from emp e
where not exists(select 1 from dept d where e.deptno = d.deptno and d.deptno = 10);
--等同于
select * from emp where deptno != 10;

--嵌套子循环
--查询工资高于SMITH工资的所有员工
select * from emp where sal > (select sal from emp where ename = 'SMITH');
--可以使用ALL关键字
--查询工资高于所有部门的平均工资的员工
select * from emp where sal > ALL(select avg(sal) from emp group by deptno);

--UPDATE和DELETE使用子查询
--可以在UPDATE语句中,使用单行子查询返回的结果给列赋值
--将empno为7499的员工工资进行更新为高工资等级的平均工资
UPDATE emp set sal = (SELECT avg(hisal) from salgrade) where empno = 7499;

--可以利用子查询返回的结果给DELETE语句的WHERE条件进行DELETE操作
--删除工资高于高工资里的平均工资的员工
DELETE from emp where sal > (select avg(hisal) from salgrade);


create table mytemp(
 id integer not null,
 age integer not null
);

insert into mytemp values(1,18);
insert into mytemp values(1,18);
insert into mytemp values(1,28);
insert into mytemp values(2,20);
insert into mytemp values(3,33);
insert into mytemp values(3,33);

select id from mytemp;

--把指定字段有重复记录的记录全部删除
--删除mytemp中id字段重复的记录
delete from mytemp where id in (select id from mytemp group by id having count(id) >= 2);

--行的标识符
--在Oracle数据库中的每一行都有一个唯一的行标识符,它用于Oracle数据库内部存储行的物理位置。
--查看emp表的信息
select ROWID , empno from emp;

--ROWNUM 
--ROWNUM可以返回结果集的行号,查询返回的第一行编号为1,第二行编号为2,依此类推
--查询emp表的相关信息
select ROWNUM , empno from emp;

--用ROWNUM实现分页
--ROWNUM行号并不是永久固定的,是每次动态重载重新生成的。
--先查询前10条记录,之后再显示5条记录,要依靠子查询完成
select * from (select ROWNUM as m , empno , ename , job , HIREDATE , sal  from emp where ROWNUM <= 10) temp
where temp.m > 5;
--按照这种方式,只需要替换掉最大最小值就可以实现分页的思想

--不同数据库实现分页的技术,SQL语法完全不同
  Oracle --> ROWNUM
  MySQL --> limit
  SQLServer --> top
  真正项目开发的分页,应该使用Java的集合框架。 List / Set -- 大集合里面套小集合