DQL---连接查询(内连接、外连接)、子查询、分页查询
一、连接查询
1、连接查询建立在有相互关系的两个表间,进行两个及两个以上的表或视图的查询。
2、对n张表进行查询,至少需要n-1个连接表的条件。
二、笛卡尔积(容易造成数据库宕机)
1、指表中每行元素与其他表的每行均组合,没有连接条件。
2、假设有两张表,表a有x条数据,表b有y条数据,则笛卡尔积查询后,会得到一张x*y条数据的表。
三、主键、外键
1、主键与外键用于维护关系型数据库的完整性。
2、主键:非空且唯一,用于标识一张表。
3、外键:用于存放另一张表的主键,外键可以重复,也可以为null。
四、等值连接、自然连接、内连接、外连接
已知两张表:
表student为:
表student_score为:
1、等值连接、非等值连接:
非等值连接一般用于给定条件进行连接,写在where语句中,只要符合了where条件,就可以连接。
等值连接指的是where连接条件相等时的连接。
【格式:】 select 字段名1, 字段名2,..., 字段名n from 表1, 表2,... ,表n where 条件 --【举例:等值连接】 select * from student stu, student_score sco where stu.id = sco.id --【结果如下图:】
--【举例:非等值连接】 select * from student stu, student_score sco where stu.id > sco.id --【结果如下图:】
2、自然连接:
是一种特殊的等值连接,要求两表之间具有重复的列,在等值连接的基础上(对相同的列进行 = 比较)去掉重复的列。
--【格式:】 select 列名1, 列名2 from 表1 natural join 表2 --【举例:】 select * from student stu natural join student_score --【可以将其理解为:消除了重复的列 ---sco.id】 select stu.id, stu.name, sco.score from student stu, student_score sco where stu.id = sco.id
3、内连接:
不能消除重复列,可以通过secect挑选字段来决定。基本与等值连接相同,使用on来指定条件。
--【格式:】 select 列名1, 列名2 from 表1 inner join 表2 on (条件) --【举例:】 select * from student stu inner join student_score sco on stu.id = sco.id
注:内连接与等值连接的区别:
(1)等值连接:2个表会先进行笛卡尔乘积运算,生成一个新表格,占据在电脑内存里,当表的数据量很大时,很耗内存,这种方法效率比较低,尽量不用。
(2)内连接:2个表根据共同id进行逐条匹配,不会出现笛卡尔乘积的现象,效率比较高,优先使用这种方法。
4、外连接
不能消除重复列,可以通过secect挑选字段来决定。
分为左外连接,右外连接,全外连接。
(1)左外连接:
以第一个关系为主,在第二个关系中找到满足条件的元素,并把他们连接起来,如果没有对应的元素,则在相应位置上的值为null。
--【格式:】 select 列名1, 列名2 from 表1 left outer join 表2 on (条件) --【举例:】 select * from student stu left outer join student_score sco on stu.id = sco.id and stu.name = 'tom'
(2)右外连接
和左外连接类似,以第二个关系为主,在第一个关系中找到满足条件的元素,并把他们连接起来,如果没有对应的元素,则在相应位置上的值为null
--【格式:】 select 列名1, 列名2 from 表1 right outer join 表2 on (条件) --【举例:】 select * from student stu right outer join student_score sco on stu.id = sco.id and stu.name = 'tom'
(3)全外连接:
全外连接是左外连接和右外连接的组合。
注:mysql中没有全外连接,可以使用union关键字 连接 左外连接 与 右外连接 实现。
--【格式:】 select 列名1, 列名2 from 表1 full outer join 表2 on (条件) --【举例:】 select * from student stu full outer join student_score sco on stu.id = sco.id and stu.name = 'tom'
五、子查询
1、子查询指的是当前查询建立在另一个查询的结果上。
2、分类:
(1)单行单列子查询:返回单行单列数据。通常写在where里。
(2)多行单列子查询:返回多行单列数据。通常写在where里。
(3)多行多列子查询:返回多行多列数据。通常写在from里,当成一个表来使用。
3、单行单列子查询
【举例:】 select stu.name from student stu where stu.id = ( select sco.id from student_score sco where sco.score = '98' )
4、多行单列子查询
【举例:】 select stu.name from student stu where stu.id in ( select sco.id from student_score sco where sco.score in ('98', '97', '96') )
5、多行多列子查询
【举例:写在where条件里】 select * from student stu where stu.id in ( select sco.id from student_score sco where sco.score in ('98', '97', '96') )
【举例:写在from条件里,当成表来用】 select * from student stu, ( select sco.id from student_score sco where sco.score in ('98', '97', '96') ) sco where stu.id = sco.id
六、分页查询
1、 rownum
rownum被称为伪列,实际上是不存在的列,用于返回标识行数据顺序的数字,自1开始,每次确定数据后自动加1。
select rownum,name,id from student
2、分页步骤(相比于mysql会略显复杂一些)
(1)先排序。
select * from student order by id desc
(2)再编号。
select rownum rw, stu.* from ( select * from student order by id desc ) stu
(3)取范围。
取范围通用套路: 从第start条开始,到第end条结束。 即从第(page -1)*pagesize + 1条开始,到第(page*pagesize)条。 其中page表示第几页,pagesize表示每页的数据。 比如第一页,每页三条记录,那么第一页显示为 1 至 3 条,第二页显示为4 至 6条, 同理…… select * from ( select rownum rw, stu.* from ( select * from student order by id desc ) stu ) where rw between 3 and 5