---一、基本查询的语句
---1.FROM字句:
---SELECT:指定你要查询的内容;FROM:数据从哪来
---SELECT<*,column[alias],...>FROM table;
---可以写*、具体的字段、函数、或表达式
---SELECT用于指定要查询的列
---FROM指定要从哪个表中查询
---如果要查询所有列,可以在SELECT后面使用*号
---如果只查询特定的列,可以直接在SELECT后面指定列名,列名之间用逗号隔开。
SELECT *FROM dept;
---2.字段的别名(使用别名)
---当一个SELECT字句中含有函数或者表达式时,查询出来的结果集中对应该字段的名字就是
---这个函数或表达式,不易理解,可读性差,为此我们可以为这样的字段单独指定别名。
SELECT ename,sal*12 FROM emp_RR;
---一个逗号','引发的血案,O(∩_∩)O哈哈~
SELECT ename,sal*12 sal FROM emp_RR;
SELECT ename,sal*12,sal FROM emp_RR;
---若希望别名区分大小写或者含有空格,那么可以使用双引号将别名括起来
SELECT ename,sal*12 "s all ary" FROM emp_RR;
SELECT ename,sal*12 AS "s all ary" FROM emp_RR;
---使用别名
---1)在SQL语句中可以通过使用列的别名改变标题的显示样式,或者表示计算结果的含义
---2)使用语法是列的别名跟在列名后,中间可以加或不加一个"AS"关键字
---3)如果希望别名中区分大小写字符,或者别名中包含字符或空格,则必须用双引号引起来
SELECT empno AS id,ename "Name",sal*12 "Annual Salary" FROM emp_RR;
--->查询ID号、姓名、年薪
---3.WHERE子句
---1)在SELECT语句中,可以在WHERE子句中使用比较操作符限制查询结果
---2)如果和数字比较,可以使用单引号引起,也可以不用
---3)如果和字符及日期类型的数据比较,则必须用单引号引起
---查询部门10号的员工信息
SELECT *FROM emp_RR WHERE deptno=10;
--->共三条
---查询职员表中职位是'SALESMAN'的职员
SELECT * FROM emp_RR WHERE job='SALESMAN';
SELECT ename,sal,job FROM emp_RR WHERE job='SALESMAN';
---4.SELECT子句
---如果只查询表的部分列,需要在SELECT后指定列名
---二、查询条件
---1.使用>,<,>=,<=,!=,<>,=
---注意:不等于是<>
---查询职员表中薪水低于2000元的职员信息
SELECT ename,sal FROM emp_RR WHERE sal<2000;
---查询职员表中不属于部门10的员工信息(!=等价于<>)
SELECT ename,sal,job,deptno FROM emp_RR WHERE deptno!=10;
---查询职员表中在1980年1月1日以后入职的职员信息,比较日期类型数据
SELECT ename,sal,hiredate FROM emp_RR WHERE hiredate>to_date('1980-1-1','YYYY-MM-DD');
---2.使用AND,OR关键字
---1)在SQL操作中,如果希望返回的结果【必须满足多个条件】,应该使用【AND】逻辑操作符连接这些条件
---2)在SQL操作中,如果希望返回的结果【满足多个条件之一即可】,应该使用【OR】逻辑操作符连接这些条件。
---查询薪水大于1000【并且】职位是'CLERK'的职员信息---AND
SELECT ename,sal,job FROM emp_RR WHERE sal>1000 AND job='CLERK';
---查询薪水大于1000【或者】职位是'CLERK'的职员信息---OR
SELECT ename,sal,job FROM emp_RR WHERE sal>1000 OR job='CLERK';
---查询薪水大于1000【并且】职位是'CLERK'【或者】'SALESMAN'的职员信息---OR
---AND,OR用来连接多个条件
SELECT ename,sal,job FROM emp_RR WHERE sal>1000 AND job='CLERK' OR job='SALESMAN';
SELECT ename,sal,job FROM emp_RR WHERE sal>1000 AND job='SALESMAN' OR job='CLERK' ;
---注意:OR的优先级是低于AND的。
---数据库理解为: sal>1000 AND job='SALESMAN'是一个条件
---所以查询的是:职位是SALESMAN薪资大于1000,或者这人是CLERK就行。对于CLERK而言,薪资没有要求大于1000.
---反过来为什么不行?
---因为SALESMAN没有薪资小于1000的。
---注意:提高优先级需要加括号()
SELECT ename,sal,job FROM emp_RR WHERE sal>1000 AND (job='SALESMAN' OR job='CLERK');
---OR的优先级低于AND,所以若希望提高OR的优先级可以使用括号。
---3.使用LIKE条件(模糊查询)
---1)比较操作符LIKE用来做模糊查询
---2)当用户在执行查询时,不能完全确定某些信息的查询条件,或者只知道信息的一部分,可以借助LIKE来实现
---3)LIKE需要借助两个通配符:
--- %:表示0到多个字符(任意一个字符)
--- _:标识单个字符(单一的一个字符)--0-多个
---这两个通配符可以配合使用,构造灵活的匹配条件
SELECT ename,job FROM emp_RR WHERE ename LIKE'_A%';
-->A前面有一个字符,A后面有任意个。
-->名字第二个字母是A的员工。
SELECT ename,job FROM emp_RR WHERE ename LIKE'__A%';
-->名字第三个字母是A的员工。(前面写两个下划线__,以此类推。)
SELECT ename,job FROM emp_RR WHERE ename LIKE'%A_';
-->名字倒数第二个字母是A的员工。
SELECT ename,job FROM emp_RR WHERE ename LIKE'%A%';
-->只要有A就行
SELECT ename,job FROM emp_RR WHERE ename LIKE'_A_D';
-->查看第二个字符是A,第四个字符是D的名字员工。
---like:像,帮我们模糊查询字符串。例如:在百度里面提供几个关键字查询。
---4.使用IN和NOT IN
---1)比较操作符IN(list)用来取出符合列表范围中的数据(满足列表中内容其中之一即可)
---2)List表示值列表,当列或表达式匹配于列表中的任何一个值时,条件为TRUE,该条记录则被显示出来
---3)IN也可以理解为一个范围比较操作符,只不过这个范围是一个指定的值列表
---4)NOT IN(list)取出不符合此列表中的数据记录
---查询职位是MANAGER或者CLERK的员工
SELECT ename,job FROM emp_RR WHERE job IN('MANAGER','CLERK');
SELECT ename,job FROM emp_RR WHERE job='MANAGER' OR job='CLERK';
--->内容多的话,比写一堆的or要方便得多。
---IN(list),NOT IN(list)
---判断在列表中或不在列表中
---IN常用在子查询中
---查询不是部门10或20的员工
SELECT ename,job,deptno FROM emp_RR WHERE deptno NOT IN(10,20);
---查询10号部门以外且工资高于1000,职位是CLERK或SALESMAN,名字中含有A的员工信息?
---列出员工的名字,工资,职位,部门号
SELECT ename,sal,job,deptno FROM emp_RR
WHERE deptno<>10 AND sal>1000
AND job IN('CLERK','SALESMAN')
AND ename LIKE'%A%';
--->共4条记录。
---5.BETWEEN...AND..(在两者之间)
---1)BETWEEN...AND..操作符用来查询符合某个值域【范围】条件的数据
---2)最常见的是使用在数字类型的数据范围上,但对字符类型和日期类型数据也同样使用
---查询薪水在1500-3000之间的职员信息
SELECT ename,sal FROM emp_RR WHERE sal BETWEEN 1500 AND 3000;
---判断在一个范围内(小的在左,大的在右)
---6.使用IS NULL和IS NOT NULL
---空值NULL是一个特殊的值,比较的时候不能使用"="号,必须使用IS NULL,否则不能得到正确的结果。
---查询哪些职员的奖金数据为NULL
SELECT ename,saL,comm FROM emp_RR WHERE comm IS NULL;
---7.使用ANY和ALL条件
---ALL和ANY不能单独使用,需要配合单行比较操作符>、>=、<、<=一起使用
-- >ANY:大于最小(大于列表的其中之一即可)
-- <ANY:小于最大
-- >ALL:大于最大(大于列表的所有)
-- <ALL:小于最小
SELECT empno,ename,job,sal,deptno FROM emp_RR WHERE sal>ANY(3500,4000,4500);
--->有病么,直接写>3500即可。
SELECT empno,ename,job,sal,deptno FROM emp_RR WHERE sal>3500;
-----将来写列表中的内容,不会给死值。都是在子查询里写(明天讲子查询)。
SELECT empno,ename,job,sal,deptno FROM emp_RR WHERE sal<ANY(3500,4000,4500);
---ANY(list),ALL(list)
---配合>、>=、<、<=一个列表使用
---ANY,ALL常用在子查询中。
---8.查询条件中使用表达式和函数
---1)当查询需要对选出的字段进行进一步计算,可以在数字列上使用算数表达式(+、-、*、/)
---2)表达式符合四则运算的默认优先级,如果要改变优先级可以使用括号
---3)算数运算主要是针对数字类型的数据,对日期类型的数据可以做加减操作,表示在一个日期值上加或减一个天数
---查询条件中使用函数
SELECT ename,sal,job FROM emp_RR WHERE ename=UPPER('scott');
--->把他名字有大小写的全部格式化后变大写
SELECT ename,sal,job FROM emp_RR;
---查询条件中使用表达式
SELECT ename,sal*12,job FROM emp_RR WHERE sal*12>50000;
---9.使用DISTINC过滤重复
---1)数据表中有可能存储相同数据的行,当执行查询操作时,默认情况会显示所有行,不管查询结果是否有重复数据
---2)当重复数据没有实际意义,经常会需要去掉重复值,使用DISTINCT实现
---查询员工的部门编码
SELECT deptno FROM emp_RR;
---查询员工的部门编码,去掉重复值
SELECT DISTINCT deptno FROM emp_RR;
---查询每个部门的职位,去掉重复值
SELECT DISTINCT deptno,job FROM emp_RR;
---DISTINC关键字
---用来将结果集中指定字段值重复的记录去除
---查看公司有哪些职位?
SELECT job FROM emp_RR;
SELECT DISTINCT job FROM emp_RR;
---注意:SELECT写了DISTINCT之后,前面不能写单独字段。
---SELECT ename,DISTINCT job FROM emp_RR;
--->ORA-00936: 缺失表达式
---多字段去重时,是这些字段值组合一样的记录不会重复出现。
---三、排序(对结果集的排序)
---1.使用ORDER BY子句
---1)对数据按一定规则进行排序操作,使用ORDER BY子句
-- SELECT<*,column[alias],...>
-- FROM table
-- [WHERE condition(s)]
-- [ORDER BY column[ASC|DESC]];
---2)必须出现在SELECT中的最后一个子句
SELECT ename,deptno FROM emp_RR ORDER BY deptno;
---排序结果集
---ORDER BY子句可以对结果集进行升序,或者降序排列。
---升序:ASC不写默认也是升序。
---降序:DESC
---ORDER BY 只能写在DQL的最后一个子句上
---查看公司中工资的排名
SELECT ename,sal,deptno FROM emp_RR ORDER BY sal;
SELECT ename,sal,deptno FROM emp_RR ORDER BY sal DESC;
--->不写就是升序,写了就是降序。DESC降序。
---2.ASC和DESC
---1)ASC用来指定升序排序(默认选项),DESC用来指定降序排序
---2)NULL值视作最大,则升序排列时,排在最后,降序排列时,排在最前
---3)不写ASC或DESC,默认是ASC,升序排列
SELECT empno,ename,mgr,deptno FROM emp_RR WHERE deptno=10 ORDER BY mgr;
---4)降序排列,必须指明
SELECT ename,sal FROM emp_RR ORDER BY sal DESC;
SELECT ename,deptno,sal FROM emp_RR ORDER BY deptno,sal;
---排序是有优先级的,首先先按照第一个字段排。
SELECT ename,deptno,sal FROM emp_RR ORDER BY deptno,sal DESC;
-->部门的升序,工资的降序。
SELECT ename,deptno,sal FROM emp_RR ORDER BY deptno DESC,sal DESC;
-->部门的降序,工资也降序。
---多字段排序时,按照ORDER BY后面第一个字段先排序,当第一个字段有重复值时,
---才按照第二个字段的值排序这些记录,依次类推所有多字段排序是有优先级的。
---排序含有NULL值的字段时,NULL被认作为最大值
---如果字段值有null怎么办?排序中只有null值时,null会被认为是最大值。
SELECT ename,comm FROM emp_RR ORDER BY comm;
SELECT ename,comm FROM emp_RR ORDER BY comm DESC;
---查看公司的所有职位,并按照职位名称排序
SELECT DISTINCT job FROM emp_RR ORDER BY job;
SELECT job FROM emp_RR ORDER BY job;
---3.多个列排序
---1)当以多列作为排序标准时,首先按照第一列进行排序,如果第一列数据相同,再以第二列排序,以此类推。
---2)多列排序时,不管正序还是倒序,每个列需要单独设置排序方式
---对职员表中的职员排序,先按照部门编码正序排列,再按照薪水降序排列
SELECT ename,deptno,sal FROM emp_RR ORDER BY deptno ASC,sal DESC;
---四、聚合函数(分组函数、多行函数)
---1.什么是聚合函数
---1)查询时需要做一些数据【统计】,比如:查询职员表中各部门职员的平均薪水,各部门的员工人数
---2)需要统计的数据并不能在职员表里直观列出,而是需要根据现有的数据计算得到结果
---3)这种功能可以使用聚合函数来实现,即:将表的全部数据划分为几组数据,每组数据统计一个结果
---4)因为是多行数据参与运算返回一行结果,也称作分组函数、多行函数、集合函数。
---2.MAX和MIN
---1)用来取得列或表达式的最大、最小值
---2)可以用来统计任何数据类型,包括数字、字符和日期
---获取机构下的最高薪水和最低薪水,参数是数字
SELECT MAX(sal) max_sal,MIN(sal) min_sal FROM emp_RR;
---最早和最晚的入职时间,参数是日期
SELECT MAX(hiredate) max_hire, MIN(hiredate) min_hire FROM emp_RR;
---3.AVG和SUM
---1)用来统计列或表达式的平均值和和值
---2)只能操作数字类型
---3)忽略NULL值
---获取机构下全部职员的平均薪水和薪水总和
SELECT AVG(sal) avg_sal, SUM(sal) sum_sal FROM emp_RR;
---聚合函数
---聚合函数是用来统计的。
---可以将结果集按照指定字段值进行统计,然后得到一个结果。
---其中有四个针对值本身统计的函数:MAX,MIN,AVG,SUM
---求最大值,最小值,平均值和总和
---还有一个对结果集记录数的统计函数:
---COUNT
---4.COUNT
---1)用来计算表中的记录条数
---2)忽略NULL值
---获取职员表中一共有多少名职员记录
SELECT COUNT(*) total_num FROM emp_RR;
---获取职员表中有多少人是有职位的(忽略没有职位的员工记录)
SELECT COUNT(job) total_job FROM emp_RR;
---求公司工资的最大,最小,平均,总和
SELECT MAX(sal),MIN(sal),AVG(sal),SUM(sal) FROM emp_RR;
---查看公司一共多少人?
SELECT COUNT(1) FROM emp_RR;
SELECT COUNT(10000) FROM emp_RR;
--->14
--->1、10000表示常量。
SELECT 1 FROM emp_RR;
--->查的是常量。
SELECT COUNT(ename) FROM emp_RR;
---5.聚合函数对空值的处理
---1)聚合函数忽略NULL值
---2)当emp表中的comm列有NULL值,比如某新入职员工没有绩效,比较两条语句的结果:
SELECT AVG(comm) avg_comm FROM emp_RR;
SELECT AVG(NVL(comm,0)) avg_comm FROM emp_RR;
---聚合函数忽略NULL值
---查看平均绩效?
SELECT AVG(comm)FROM emp_RR;
--->550
---查看绩效总和?
SELECT AVG(comm),SUM(comm) FROM emp_RR;
--->550,2200(这里除以的是4,没有绩效的就连人都不是啦?!O(∩_∩)O哈哈哈~)
SELECT comm FROM emp_RR;
SELECT AVG(comm) FROM emp_RR;
SELECT AVG(NVL(comm,0)) FROM emp_RR;
---空值函数(见day02最后一个内容)
---NVL(a1,a2)
---当a1为NULL时,函数返回a2,否则返回a1自身,所有函数作用是将NULL值替换为指定值。
SELECT ename,sal,comm,sal+NVL(comm,0) FROM emp_RR;
---计算员工月收入
SELECT ename,sal,comm,sal+NVL(comm,0)as "salary"FROM emp_RR;
SELECT COUN(comm)FROM emp_RR;
--->忽略NULL值,不进行统计了。
SELECT COUN(1)FROM emp_RR;
--->写1或*就不会有NULL值出现。
SELECT * FROM emp_RR;
---查看20号部门的平均工资是多少?
SELECT sal,deptno FROM emp_RR WHERE deptno=20;
SELECT AVG(sal) FROM emp_RR WHERE deptno=20;
---以下SQL执行会报错!
---SELECT MAX(sal),ename FROM emp_RR;
--->ORA-00937: 不是单组分组函数
--->MAX(sal):只会出现1条记录
--->ename:会单独出来14条
---不是把最高的名字列出来,有了聚合函数后,是不能单独写字段的。非要写可以,下午讲。
---查看每个部门的平均工资?
SELECT AVG(sal),deptno FROM emp_RR
GROUP BY deptno;
---分组
---GROUP BY 子句
---GROUP BY 子句可以将结果集按照指定字段值一样的记录看作同一组,配合聚合函数使用
---可以对每组的数据进行统计并得出结果。
---当SELECT子句中使用了聚合函数时,那么凡不在聚合函数中的单独字段
---都必须出现在GROUP BY子句中。
---每个职位的最高工资和最低工资是多少?
SELECT MAX(sal),MIN(sal),job FROM emp_RR
GROUP BY job;
---GROUP BY:不只是用单字节分组,也允许我们按照多个字段进行分组。
---查看每个部门的平均工资,但前提是该部门的平均工资要高于2000.
SELECT AVG(sal),deptno FROM emp_RR
WHERE AVG(sal)>2000
GROUP BY deptno;
--->ORA-00934: 此处不允许使用分组函数
--->WHERE AVG(sal)>2000 此处不允许
--->时机不对,where是做过滤条件,此处不是where过滤的职责。
--->where什么时候做过滤?
--->在第一次检索表检索数据的时候,来生成结果集的时候,进行过滤的。哪条数据是从where中查询出来,哪条数据不要。
---上面的SQL语句会报错,WHERE中不能使用聚合函数作为过滤条件,原因在于过滤的时机不对。
---WHERE是在第一次检索表时,逐行过滤数据以产生查询结果集时使用的。
---而聚合函数是用来统计,那么前提是有数据所以要将所有数据查询出来才能统计,之后
---可以进行过滤,这实际是在WHERE之后进行的。
---若想使用聚合函数的结果进行过滤,那么需要使用HAVING子句。
---HAVING必须跟在GROUP BY子句之后,作用是添加过滤条件将不满足的分组去除。
---而HAVING中允许使用聚合函数作为过滤条件。
SELECT AVG(sal),deptno FROM emp_RR
GROUP BY deptno;
--->每个部门去重的平均工资
SELECT AVG(sal),deptno FROM emp_RR
GROUP BY deptno HAVING AVG(sal)>2000;
---查看部门平均工资高于2000的这些部门的最高工资是多少?
SELECT MAX(sal),deptno FROM emp_RR
GROUP BY deptno HAVING AVG(sal)>2000;
---五、分组
---1.GROUP BY 子句
---SELECT<*,column[alias],...>
---FROM table[WHERE condition(s)]
---[GROUP BY group_by_expression]
---[HAVING group_condition]
---[ORODER BY column[ASC|DESC]];
---1)当希望得到每个部门的平均薪水,而不是整个机构的平均薪水
---2)把整个数据表按部门划分成一个个小组,每个小组中包含一行或多行数据,在每个小组中使用分组函数
--- 进行计算,每组返回一个结果
---3)划分的小组有多少,最终的结果集行数就有多少
---2.分组查询
---分组查询的功能
---3.HAVING子句
---1)HAVING子句用来对分组后的结果进一步限制,比如按部门分组后,得到每个部门的最高薪水,可以继续限制输出结果。
---2)必须跟在GROUP BY后面,不能单独存在
---查询每个部门的最高薪水,只有最高薪水大于4000的记录才被输出显示
SELECT deptno,MAX(sal) max_sal FROM emp_RR
GROUP BY deptno HAVING MAX(sal)>4000;
---多个字段分组
---GROUP BY使用多个字段分组时,是将这些字段值的组合一样的记录看作一组。
---查看每个部门每种职位各是多少人?
SELECT COUNT(*) ,job,deptno FROM emp_RR
GROUP BY deptno,job;
SELECT COUNT(*) ,job FROM emp_RR
GROUP BY deptno,job;
SELECT COUNT(*) FROM emp_RR
GROUP BY deptno,job;
---结果是一样:有点像DISTINC
---DISTINC关键字
---用来将结果集中指定字段值重复的记录去除
---查看公司有哪些职位?
SELECT job FROM emp_RR;
SELECT DISTINCT job FROM emp_RR;
---注意:SELECT写了DISTINCT之后,前面不能写单独字段。
---SELECT ename,DISTINCT job FROM emp_RR;
--->ORA-00936: 缺失表达式
---多字段去重时,是这些字段值组合一样的记录不会重复出现。
---六、查询语句执行顺序
---1.查询语句执行顺序
---1) from子句:执行顺序为从后往前、从右到左
--- 数据量较少的表尽量放在后面(---关联查询,哪张表数据少就放在后面。数据量越多的表越放在前面。)
---2) where子句:执行顺序为自下而上、从右到左
--- 将能过滤掉最大数量记录的条件写在Where子句的最右
---3) group by---执行顺序从左往右分组
--- 最好在GROUP BY 前使用WHERE将不需要的记录在GROUP BY之前过滤掉
---4) having子句:消耗资源
--- 尽量避免使用,HAVING 会在检索出所有记录之后才对结果集进行过滤,需要排序等操作
---5) select子句:少用*号,尽量取字段名称。
--- ORACLE在解析的过程中,通过查询数据字典将* 号依次转换成所有的别名,消耗时间
---6) order by子句:执行顺序为从左到右排序,消耗资源
---SQL(关联查询)
---2.关联基础
---1)关联的概念
---1.1)实际应用中所需要的数据,经常会需要查询两个或两个以上的表
---1.2)这种查询两个或两个以上数据表或视图的查询叫做连接查询
---1.3)连接查询通常建立在存在相互关系的父子表之间
---SELECT table1.column,table2.column FROM table1,table2
---WHERE table1.column1=table2.column2;
SELECT ename,sal,deptno FROM emp_RR;
SELECT deptno,dname,loc FROM dept_RR;
--->用这两张表做关联:
---查看每个员工的名字以及其所在部门的名字?
SELECT ename,dname FROM emp_RR,dept_RR
WHERE deptno=deptno;
--->ORA-00918: 未明确定义列
SELECT ename,dname FROM emp_RR,dept_RR
WHERE emp_RR.deptno=dept_RR.deptno;
SELECT ename,deptno,dname FROM emp_RR,dept_RR
WHERE emp_RR.deptno=dept_RR.deptno;
--->ORA-00918: 未明确定义列
--->这两张表上,都有这个字段的deptno,到底从哪张表上去这个字段的值?
SELECT emp_RR.ename,emp_RR.deptno,dept_RR.dname FROM emp_RR,dept_RR
WHERE emp_RR.deptno=dept_RR.deptno;
---假设这两张表名字很长,若跨七张表查询,名字很长,就会很恶心。
---SELECT employee.ename,employee.deptno,department.dname FROM employee,department
---WHERE employee.deptno=department.deptno;
---此时,可以加别名。
---表,可以加别名。注意:别名不要写得比表名还长,否则这样就失去实际意义了。
---对于查询的某个字段在多张表上同时存在,而在查询时出现的未明确定义列的问题,
---我们可以使用表名或表别名来指定该字段来自哪张表。
SELECT e.ename,e.deptno,d.dname FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno;
---过滤条件和连接条件必须同时存在的。
---关联查询中,过滤条件要与连接条件同时满足。
---查看在NEW YORK工作的员工---NEW YORK 在dept表上,是10号部门的员工。
SELECT e.ename,e.deptno,d.dname,d.loc FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno
AND d.loc='NEW YORK';
---关联查询
---联合多张表查询数据即关联查询,查询的结果集中的字段来自多张表。
---关联查询的重点是连接条件,数据库是根据连接条件对表中的数据做关联然后查询内容的。
---关联查询通常要加连接条件,不写连接条件会出现“笛卡尔积”。
---笛卡尔积通常是一个无意义的结果集。
---笛卡尔积是将关联查询表中的数据一一连接一遍而产生的结果集,数据量为关联查询表数据量的乘积。
---3.笛卡尔积
---1)笛卡尔积指做关联操作的每个表的每一行都和其他表的每一行做组合,假设两个表的记录条数分别是X和Y,
--- 笛卡尔积将返回X*Y条记录。
---2)关联查询时不指定连接条件就会出现笛卡尔积,实际开发中要避免这种情况的出现,通常笛卡尔积没有意义。
SELECT COUNT(*) FROM emp_RR;
--->14条记录
SELECT COUNT(*) FROM dept_RR;
--->4条记录
SELECT emp_RR.ename,dept_RR.dname FROM emp_RR,dept_RR;
SELECT e.ename,d.dname FROM emp_RR e,dept_RR d;
--->56条记录
---数据库是宁可错杀一万,不放过一个。
---4.等值连接(一张表的字段值,等于另一张表的字段值)
---连接查询中最常见的一种,通常是在有主外键关联关系的表间建立,并将连接条件设定为有关系的列,
---使用的等号"="连接相关的表
---查询职员的姓名、职位以及所在部门的名字和所在城市,使用两个相关的列做等值操作
---SELECT e.ename,e.job,d.dname,d.loc FROM emp e,dept d
---WHERE e.deptno=d.deptno;
SELECT e.ename,e.job,d.dname,d.loc FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno;
---六、关联查询
---1.内连接(实现的效果和关联查询是一样的,但是写法不同。)
--- 内连接返回所有满足连接条件的记录。
---SELECT e.ename,d.dname FROM emp e,dept d
---WHERE e.deptno=d.deptno;
---SELECT e.ename,d.dname FROM emp e JOIN dept d --->JOIN...ON...:连接两个表
---ON(e.deptno=d.deptno); --->连接条件
---JOIN xxxxxx--->连接第三张表
---ON d.xxx=x.xxx
---SELECT e.ename,d.dname FROM emp e,dept d,xxxx x
---WHERE e.deptno=d.deptno
---AND d.xxx=x.xxx
---内连接
---内连接也是用来实现关联查询的。
SELECT e.ename,d.dname FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno;
SELECT e.ename,d.dname FROM emp_RR e JOIN dept_RR d
ON(e.deptno=d.deptno);
--->无括号也行。
SELECT e.ename,d.dname FROM emp_RR e JOIN dept_RR d
ON e.deptno=d.deptno;
--->不同的两个标准:SQL98和SQL92,JOIN...IN...是SQL92新推出的。
---内连接是比关联查询快的(有资源消耗的)。当写成普通查询时,数据库会把它转为内连接,然后再去执行。
---后者,结构更清晰。
---为什么只有13条记录?????????????没有Scott,Scott在50号部门,而dept部门表没有50号部门。
---关联查询,是忽略不满足连接条件的记录。连不上线的,是不会出现在查询结果集中的。
SELECT * FROM emp_RR;
SELECT * FROM dept_RR;
---查看在NEW YORK工作的员工---NEW YORK 在dept表上,是10号部门的员工。
SELECT e.ename,e.deptno,d.dname,d.loc FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno
AND d.loc='NEW YORK';
---用JOIN...ON...(内连接)
SELECT e.ename,e.deptno,d.dname,d.loc FROM emp_RR e JOIN dept_RR d
ON e.deptno=d.deptno
WHERE d.loc='NEW YORK';
---2.外连接
---1)内连接返回满足连接条件的数据记录
---2)有些情况下,需要返回那些不满足连接条件的记录,需要使用外连接
---3)外连接不仅返回满足连接条件的记录,还将返回不满足连接条件的记录
---4)驱动表的概念
---SELECT table1.column,table2.column
---FROM table1 LEFT|RIGHT|FULL [OUTER] JOIN table2
---ON table1.column1=table2.column2;
---emp表做驱动表
---SELECT e.ename,d.dname FROM emp e LEFT OUTER JOIN dept d
---ON e.deptno=d.deptno;
---dept表做驱动表
---SELECT e.ename,d.dname FROM emp e RIGHT OUTER JOIN dept d
---ON e.deptno=d.deptno;
---全外连接
---1.全外连接是指,除了返回满足连接条件的记录,还会返回不满足连接条件的所有其他行。
---2.是左外连接和右外连接查询结果的总和。
---SELECT e.ename,d.dname FROM emp e FULL OUTER JOIN dept d
---ON e.deptno=d.deptno;
---注意:普通的关联查询也可以做这件事。
---关联查询的外连接写法:
SELECT e.ename,d.dname FROM emp_RR e,dept_RR d
WHERE e.deptno=d.deptno(+);
SELECT e.ename,d.dname FROM emp_RR e,dept_RR d
WHERE e.deptno(+)=d.deptno;
---SELECT e.ename,d.dname FROM emp_RR e,dept_RR d
---WHERE e.deptno(+)=d.deptno(+);
---只有全外连接没有。
---把+加号写左边,是把右边显示全。反之...
---加号+写哪边,哪边加NULL.
---外连接
---外连接在关联查询中除了可以将满足连接条件的记录查询出来之外,还可以将不满足连接条件的记录查询出来。
---外连接分为:
--- 1)左外连接:以JOIN左侧表作为驱动表(所有数据都要显示出来),
--- 那么当该表某条记录不满足连接条件时,来自右侧表中的字段值全部为空。
--- 2)右外连接:全外连接。
SELECT e.ename,e.sal,d.dname,d.loc FROM emp_RR e LEFT OUTER JOIN dept_RR d
ON e.deptno=d.deptno;
--->左外连接,把emp职员表中,scott在dept部门表中没有50号部门的记录信息是NULL值。
SELECT e.ename,e.sal,d.dname,d.loc FROM emp_RR e RIGHT OUTER JOIN dept_RR d
ON e.deptno=d.deptno;
--->右外连接,把dept部门表中,没有operations信息在emp职员表中是NULL值。
SELECT e.ename,e.sal,d.dname,d.loc FROM emp_RR e FULL OUTER JOIN dept_RR d
ON e.deptno=d.deptno;
--->全外连接。
---3.自连接
---1)自连接是一种特殊的连接查询,数据的来源是一个表,即关联关系来自于单表中的多个列
---2)表中的列参照同一个表中的其它列的情况称作自参照表
---3)自连接时通过将表用别名虚拟成两个表的方式实现,可以是等值或不等值连接
---查询每个职员的经理名字,以及他们的职员编码
---SELECT worker.empno w_empno,worker.ename w_ename,manager.empno m_empno,manager.ename m_ename
---FROM emp worker join emp manager
---ON worker.mgr=manager.empno;
---Emp员工这张表上,也有自连接问题。
---公司里面大家都是员工,员工之间也存在上下级,上面有boss,下面有大区经理,下面有部门经理... ...
---自连接
---当前表的记录与当前表的多条记录,有对应关系
---自连接解决数据属性相同,但是又存在上下级关系的树状结构数据使用。
---ename:自己员工的工号
---mgr:上司的工号
SELECT empno,ename,mgr FROM emp_RR;
---查看每个员工的名字以及其上司的名字?
SELECT e.ename,m.ename
FROM emp_RR e,emp_RR m
WHERE e.mgr=m.empno;
--->普通查询
SELECT e.ename,m.ename
FROM emp_RR e JOIN emp_RR m
ON e.mgr=m.empno;
--->关联查询(结果一样)
---查询每个职员的经理名字,以及他们的职员编码
---SELECT worker.empno w_empno,worker.ename w_ename,manager.empno m_empno,manager.ename m_ename
---FROM emp worker join emp manager --->JOIN同一个表
---ON worker.mgr=manager.empno;