连接查询
又称为,多表查询,或者是多表连接.
使用场景:当我们查询语句中使用到多个表中的自读那,那么我们就需要使用多表的连接查询.
运行结果如下:
分析:因为这样写SQL语句,在语法上时行得通的,但是相当于我们拿着beauty表中的每行记录去和boys表中的每一条记录进行匹配.因为我们没有添加筛选条件或者是匹配条件,所以导致这种结果.这种现象称之为笛卡尔积;
笛卡儿积:
笛卡尔积现象:表1有m行,表2有n行,那么结果就是m*n行记录.
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件.
分类:
按照年代分类:
sql92:仅仅支持内连接
sql99:支持内连接,外链接(支持外链接中的左外和右外),交叉连接
按照功能分类:
内连接
等值连接
非等值连接
自连接
外链接
左外连接
右外连接
全外连接
交叉连接
等值连接
总结:等值连接其实就是连接条件使用了等于号进行连接
多表的等值连接显示的结果为多表的交集部分
n张表等值连接,那么至少需要(n-1)个连接条件
多表之间是没有顺序的,谁在前后无所谓.
由于一般多表之间的字段名可能存在重复的现象,那么都需要为表其别名,.起了别名之后,我们就不能使用原来的表明对表中的字段进行约束,需要使用别名进行约束.
可以搭配所有的查询子句使用,例如之前的,排序,分组,筛选进行结合.
非等值连接
总结:非等值连接说白了,就是连接条件不是使用等于号进行连接的.
例如:查询出员工的工资级别
select salary ,job_grade from employees e,job_grade j where e.sarlary between j.least_lavel and high_level;
非等值连接也是可是和之前学习到的子句一起使用.
自连接
自连接其实说白了也是属于等值连接,只不过是自己连接自己.相当于把我们之前的一张表,当成两张表甚至是多张表进行连接.
自连接的关键就是给自己的表起别名,因为同一张表如果不起别名对字段进行限制,那么就会报错.
排序查询小结
语法:
select 查询列表
from 表名称\
where 筛选条件
order by 排序条件(asc || desc);
特点:
asc:升序排列,如果不写默认就是升序.desc:降序.
排序列表支持单个字段,多个字段,函数,表达式,别名.
order by 的位置一般放在查询语句的最后,除了limit语句之外.
1.单行函数:
concat:连接
lpad:左填充
rpad:右填充
instr:获取子串在目标串中第一次出现的下标,(下标是从1开始的)
substr:截取字符串
trim:去除首尾的空格或者是指定的字符
length:获取字符的长度
upper:转换为大写
lower:转换为小写
replace:替换
2.数学函数
ceil:向上取整
floor:向下取整
round:四舍五入
mod:取模
turncate:截断
rand:获取随机数,默认产生的是0-1之间的小数.无线接近于1.
3.日期函数
now:返回系统当前的时间和日期
year:返回年
mounth:返回月
day:返回日
curtime:返回系统当前的时间
curdate:返回系统当前的日期
date_formate:将日期转换成字符
str_to_date:将字符转换为日期
datediff:返回两个日期相差的天数.
4.其他函数
version:返回当前数据库服务器的版本号.
database:显示当前打开的数据库.
user:当前用户
password("字符"):返回当前用户密码的形式.
md5("字符"):返回md5的加密形式.
5.流程控制函数
if("条件表达式,表达式1,表达式2"),如果条件表达式成立,则返回表达式1,否则则返回表达式2.
2.分组函数:
max();最大值
min();最小值
sum():求和
avg();平均值
count();求数量.
特点:
sum 和 avg一般用于处理数值类型.
max,min,count可以用来处理任何数据类型.
以上分组函数都绝对忽略null值,和null值运算的结果还是null.
都可以和distinct搭配使用,来实现去重的目的.
分组查询
语法:
select 分组函数,分组后的字段 from 表名称
where 筛选条件(如果有的话就加筛选)
group by 分组后的字段
having 分组后的筛选
order by 排序列表.
特点:
使用关键字 筛选的表 位置
分组前筛选 where 原始表 group by之前
分组后筛选 having 分组后的结果集 group by之后.
sql99语法
select 查询列表
from 表1 别名 [连接类型]
join 表2 别名
on 连接条件
[where 筛选条件]
[group by 分组条件]
[having 筛选条件]
[order by 排序条件]
分析:sql99和sql92的区别就是,首先多张表之间不是使用逗号进行连接,而是使用了关键字join,连接条件不是使用where而是使用了on关键字,之后的语法都差不多没我们可以根据需要具体的添加相应的条件.
内连接:使用inner来表示连接类型
外链接
左外连接:left outer (outer是可以省略的)
右外连接:right outer (同上)
全外连接:full outer (同上)
交叉连接:cross join
内连接
语法:
select 查询列表 from 表1 别名 inner join 表2 别名
on 连接条件 {其他的条件可以继续追加}
内连接的分类:
等值连接:例子如下:查询出员工名和部门名
select last_name,department_name from employee e inner department d
on e.department_id = d.department_id;
特点:可以添加排序,分组,筛选.
inner是可以省略的
连接条件放在关键字on之后.,筛选条件放在where之后.
该等值连接和sql92实现的效果是一样的.最后都是展示出多表的交集部分.
非等值连接:
和等值连接得语法类似,只不过使用的不是等于号进行连接
自连接:
和等值连接的语法是一样的,只不过要连接的两张甚至是多张表都是同一张表.
外连接
应用场景:用于查询一个表中有而另外一个表中没有的数据,和内连接的区别就在于此,内连接适用于查询多表的交集并且显示.
特点:
1.外连接的查询结果其实是主表中的所有记录
如果从表中有与之相匹配的,则显示与之匹配的值,
如果从表中没有与之相匹配的,则显示null.
总结 外连接的结果 = :内连接的结果 + 主表中有而从表中没有的记录
2.主表和从表的确认
左外连接:left outer join 左边的就是主表
右外连接:right outer join 右边的是主表
一般情况下,当我们所需的结果多数来源的表,是要被当成主表的.
3.左外和右外交换两个表的顺序,可以实现同样的结果.左外和右外的区别就是除了关键字使用的有所不同,语法上时没有其他的区别的.
4.如果我们只是需要其中的一部分数据,我们可以通过加筛选条件where + 表的主键 is null进行数据的筛选.
全外连接
sql99语法中,mysql是不支持全外连接的.,
全外链接 = 内连接的结果集 + 表1中含有但是表2中没有的 + 表2中有但是表1没有的数据
它查询的结果集的范围是最广的,,我们也可以通过添加筛选条件对结果进行空值,例如只要其中一部分结果.
交叉连接
这个交叉连接使用的关键字是cross join,听起来感觉是比较的高大上,其实就是sql92语法中的逗号而已,它的结果就是笛卡尔的乘积,例如 表1有4行,表2有11行记录,那么交叉连接的结果就是
select b1.* ,b2.* from boys b1 cross join beauty b2;
sql92和sql99的区别
功能:SQL99支持的功能比较多一点
可读性:SQL99实现了连接条件和筛选条件的分离,可读性比较的高.
子查询
定义:出现在其他语句中的select语句,都可以成为子查询或者是内查询.外部的查询语句则称为主查询.或者是外查询.如下图:
分类:
按照子查询出现的位置:
select后面:
只能放标量子查询
from后面:
支持表子查询
重点:where或者having后面:
支持标量子查询,列子查询,也支持行子查询(但使用的较少)
exits后面(成功为相关子查询):
支持表子查询
按照结果集的行列数不同:
标量子查询(结果集只有一行一列)也被称为是单行子查询
列子查询(结果集只有一列多行)
行子查询(结果集可以有一行多列)
表子查询(结果集一般为多行多列)
where和having之后
1:标量子查询(单行子查询)
2:列子查询(结果集是一列多行,也称为是多行子查询)
3:行子查询(查询结果中多列多行)
特点:
子查询放在小括号内
子查询一般放在条件的右侧
标量子查询一般,搭配着单行操作符使用.(包括,> <, >= , <= <>)
子查询的执行优于主查询的执行,因为主查询中是用了子查询的结果集
列子查询一般搭配着我们的多行操作符使用,(in, any/some, all)
例如:
非法使用标量子查询
非法的使用标量子查询主要是包括,子查询结果集不是标量子查询然后和大于等符号搭配使用,另外标量子查询的结果为空也是属于非法的.
多行子查询
多行子查询要配合着多行比较操作符进行使用,和以前不同之处就是,以前的操作符后面跟的是常量列表集合,而是把每一个值都替换成了查询语句.
子查询位于select后面
select的查询条件中如何包含有子查询,那么该子查询的结果返回一定是一行一列,否则会报语法错误.
子查询位于from之后
一般来说,放在from之后的都是一个具体的表格,也就是说把我们子查询得到的数据当成了数据源使用.唯一需要注意的是,需要给子查询的结果起一个别名,因为相当于把结果集当成了一张表使用,如果没有别名的话,这个表示没有名称的.
子查询位于exists之后(也称为是相关子查询)
exists(一个完整的查询语句a),如果查询a有值,表示为true,那么总体语句返回的就是1,没有值,表示为false,返回的就是0
一般来说,能用exists的查询,都能够使用in等关键字进行代替完成,所以它的使用是比较的少.和in的主要差别就是在于,in后的子查询会先于主查询执行,而exists后的子查询会在主查询执行之后执行,主要是根据子查询中的条件对主查询的结果集进行过滤.
分页查询
上图上面有很多的可选条件,如果所有的都算上,我们来说一下它的执行顺序:
1,from 表名称 — 2.join变成笛卡尔乘积 — 3.on进行过滤 — 4.where进行分组前筛选 — 5.group by进行分组 — 6.having进行分组后的筛选 — 7.order by进行排序 — 8.select语句 — 9.limit进行分页.
以上所有的步骤每次执行一个之后,都会生成相应的虚拟的表.
如果我们起始条目的下标是表的第一个元素的话,是可以省略offset的.
执行的效果是一样的,都是查询出前5条数据.
特点
联合查询
关键字:union:联合,合并的意思,就是说,把多条查询语句的结果合并成一个结果.
相当于把一个大的查询拆分成多个小查询然后使用union进行连接
应用场景
当我们要的查询结果需要来自多个表,并且多个表之间没有直接的联系,但是查询的信息是一致的.(查询信息指的就是查询列表)
特点:
在使用联合查询时,多个小查询语句的查询列数必须是一致的
多条查询语句的查询的每一列的类型和顺序最好保持一致
联合查询中,使用union关键字默认是自动去重的,我们可以使用union all来显示重复项