1.基本查询回顾
准备测试表:
• 下面给出三张表,分别是员工表(emp)、部门表(dept)和工资等级表(salgrade)。
• 后续所要进行的查询操作都将以这三张表作为数据源,包括基本查询和复合查询。
员工表(emp)中包含如下字段 部门表(dept)中包含如下字段 工资等级表(salgrade)中包含如下字段 • 雇员编号(empno)
• 雇员姓名(ename)
• 雇员职位(job)
• 雇员领导编号(mgr)
• 雇佣时间(hiredate)
• 工资月薪(sal)
• 奖金(comm)
• 部门编号(deptno)
• 部门编号(deptno)
• 部门名称(dname)
• 部门所在地点(loc)
• 等级(grade)
• 此等级最低工资(losal)
• 此等级最高工资(hisal)
员工表(emp)中的内容如下:
部门表(dept)中的内容如下:
工资等级表(salgrade)中的内容如下:
查询工资高于500或岗位为MANAGER的员工,同时要求员工姓名的首字母为大写的J:
在where子句中指明筛选条件为工资高于500或岗位为MANAGER,并且通过模糊匹配指明员工姓名的首字母为大写的J,在select的column列表中指明要查询的列为姓名、工资和岗位。如下:
查询员工信息,按部门号升序而员工工资降序显示:
在select的column列表中指明要查询的列为姓名、部门号和工资,在order by子句中依次指明按部门号排升序和按员工工资排降序,即不同部门的员工按照部门号排升序,而同一部门的员工按员工工资排降序。如下:
查询员工信息,按年薪降序显示:
在select的column列表中指明要查询的列为姓名和年薪,在order by子句中指明按年薪进行降序排序。如下:
说明一下:
• 由于NULL与任何值做计算得到的结果都是NULL,因此在计算年薪时不能直接用月薪的12倍加上每个员工的奖金,这样可能导致得到的年薪为NULL值。
• 在计算每个员工的年薪时,应该通过ifnull函数判断员工的奖金是否为NULL,如果不为NULL则ifnull函数返回员工的奖金,如果为NULL则ifnull函数返回0,避免让NULL值参与计算。
查询工资最高的员工的姓名和岗位:
解决该问题需要进行两次查询,先对员工表进行一次查询得到最高工资,然后再根据最高工资对员工表进行一次查询,得到工资等于最高工资的员工的姓名和岗位。如下:
此外,这种问题还可以使用子查询,将第一次查询的SQL语句用括号括起来,作为最高工资直接在第二次查询的SQL语句中使用。如下:
查询工资高于平均工资的员工信息:
解决该问题也需要进行两次查询,先对员工表进行一次查询得到平均工资,然后再根据平均工资对员工表进行一次查询,筛选出工资高于平均工资的员工信息,该问题同样可以使用子查询。如下:
查询每个部门的平均工资和最高工资:
在group by子句中指明按照部门号进行分组,在select语句中使用avg函数和max函数,分别查询每个部门的平均工资和最高工资。如下:
查询平均工资低于2000的部门号和它的平均工资:
在group by子句中指明按照部门号进行分组,在select语句中使用avg函数查询每个部门的平均工资,在having子句中指明筛选条件为平均工资小于2000。如下:
查询每种岗位的雇员总数和平均工资:
在group by子句中指明按照岗位进行分组,在select语句中使用count函数和avg函数,分别查询每种岗位的雇员总数和平均工资。如下:
2.多表查询
多表查询:
• 上面的基础查询都是在一张表的基础上进行的查询,而实际开发中往往需要将多张表关联起来进行查询,这就叫做多表查询。
• 在进行多表查询时,只需要将多张表的表名依次放到from子句之后,用逗号隔开即可,这时MySQL将会对给定的这多张表取笛卡尔积,作为多表查询的初始数据源。
• 多表查询的本质,就是对给定的多张表取笛卡尔积,然后在笛卡尔积中进行查询。
所谓的对多张表取笛卡尔积,就是得到这多张表的记录的所有可能有序对组成的集合,比如下面对员工表和部门表进行多表查询,由于查询语句中没有指明筛选条件,因此最终得到的结果便是员工表和部门表的笛卡尔积。说明一下:
• 员工表和部门表的笛卡尔积由两部分组成,前半部分是员工表的列信息,后半部分是部门表的列信息。
• 对员工表和部门表取笛卡尔积时,会先从员工表中选出一条记录与部门表中的所有记录进行组合,然后再从员工表中选出一条记录与部门表中的所有记录进行组合,以此类推,最终得到的就是这两张表的笛卡尔积。
笛卡尔积的初步过滤:
需要注意的是,对多张表取笛卡尔积后得到的数据并不都是有意义的,比如对员工表和部门表取笛卡尔积时,员工表中的每一个员工信息都会和部门表中的每一个部门信息进行组合,而实际一个员工只有和自己所在的部门信息进行组合才是有意义的,因此需要从笛卡尔积中筛选出员工的部门号和部门的编号相等记录。如下:
注:进行笛卡尔积的多张表中可能会存在相同的列名,这时在选中列名时需要通过
表名.列名
的方式进行指明。
显示部门号为10的部门名、员工名和员工工资:
由于部门名只有部门表中才有,而员工名和员工工资只有员工表中才有,因此需要同时使用员工表和部门表进行多表查询,在where子句中指明筛选条件为员工的部门号等于部门编号,并且部门号为10的记录。如下:
注:第一个筛选条件已经筛选出员工的部门号和部门编号相等的记录,因此在筛选部门号等于10的部门时,可以使用员工表中的部门号,也可以使用部门表中的部门编号。
显示各个员工的姓名、工资和工资级别:
由于员工名和工资只有员工表中才有,而工资级别只有工资等级表中才有,因此需要同时使用员工表和工资等级表进行多表查询,在where子句中指明筛选条件为员工的工资在losal和hisal之间的记录。如下:
注:
1.员工表和工资等级表的笛卡尔积中,将每一个员工的信息和每一个工资等级的信息都进行了组合,而实际一个员工只有和自己的工资对应的工资等级信息进行组合才是有意义的。
2.因此需要根据各个工资等级的最低工资和最高工资判断一个员工是否属于该工资等级,进而筛选出有意义的记录。