进阶6:连接查询
含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:表1 有m行,表2有n行,结果=m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类
按年代分类:
- sql92标准:仅仅支持内连接(等值、非等值、自连接)
- sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接
按功能分类:
- 内连接:等值连接、非等值连接、自连接
- 外连接:左外连接、右外连接、全外连接
- 交叉连接
sql92标准
1、等值连接
特点:
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序、分组、筛选
案例1 :查询女神名和对应的男神名
SELECT
NAME,
boyName
FROM
boys,
beauty
WHERE beauty.`boyfriend_id` = boys.`id` ;
结果:
案例2:查询员工名和对应的部门名
SELECT
last_name,
department_name
FROM
employees,
departments
WHERE employees.`department_id` = departments.`department_id` ;
结果:
(1)为表起别名
- 提高语句的简洁度
- 区分多个重名的字段
注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定
案例:查询员工名、工种号、工种名
SELECT
last_name,
e.job_id,
job_title
FROM
employees AS e,
jobs AS j
WHERE e.`job_id` = j.`job_id` ;
结果:
(2)两个表的顺序是可以调换
案例:查询员工名、工种号、工种名
SELECT
e.last_name,
e.job_id,
j.job_title
FROM
jobs j,
employees e
WHERE e.`job_id` = j.`job_id` ;
(3)可以加筛选
案例1:查询有奖金的员工名、部门名
SELECT
e.last_name,
d.department_name,
commission_pct
FROM
employees e,
departments d
WHERE d.`department_id` = e.`department_id`
AND e.`commission_pct` IS NOT NULL ;
结果:
案例2:查询城市名中第二个字符为o的部门名和城市名
SELECT
department_name,
city
FROM
departments d,
locations l
WHERE d.`location_id` = l.`location_id`
AND l.`city` LIKE "_o%" ;
结果:
(4)可以加分组
案例1:查询每个城市的部门个数
SELECT
COUNT(*) AS 个数,
city
FROM
departments d,
locations l
WHERE d.`location_id` = l.`location_id`
GROUP BY l.`city` ;
结果:
案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
SELECT
d.`department_name`,
d.`manager_id`,
MIN(salary)
FROM
departments d,
employees e
WHERE d.`department_id` = e.`department_id`
AND e.`commission_pct` IS NOT NULL
GROUP BY department_name,
d.`manager_id` ;
结果:
(5)可以加排序
案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
SELECT
job_title,
COUNT(*) 员工个数
FROM
employees e,
jobs j
WHERE e.`job_id` = j.`job_id`
GROUP BY j.`job_title`
ORDER BY COUNT(*) DESC ;
结果:
(6)可以实现三表连接
案例:查询员工名、部门名和所在的城市
SELECT
last_name,
department_name,
city
FROM
departments d,
employees e,
locations l
WHERE d.`department_id` = e.`department_id`
AND d.`location_id` = l.`location_id`
AND city LIKE 'S%'
ORDER BY department_name DESC ;
结果:
2、非等值连接
语法:
SELECT 查询列表
FROM 表1 AS 别名,表2 AS 别名
WHERE 非等值的连接条件
案例:查询员工的工资和工资级别
SELECT
salary,
grade_level
FROM
employees e,
job_grades g
WHERE salary BETWEEN g.`lowest_sal`
AND g.`highest_sal` ;
结果:
3自连接
语法:
SELECT 查询列表
FROM 表1 AS 别名1,表1 AS 别名2
WHERE 条件
案例:查询 员工名和上级的名称
SELECT
e.employee_id,
e.last_name,
m.employee_id,
m.last_name
FROM
employees e,
employees m
WHERE e.`manager_id` = m.`employee_id` ;
结果:
测试
1、显示员工表的最大工资,工资平均值
SELECT
MAX(salary) 最大工资,
AVG(salary) 平均工资
FROM
employees ;
结果:
2、查询员工表的employee_id,job_id,last_name,按department_id降序,salary升序
SELECT
employee_id,
last_name,
job_id
FROM
employees
ORDER BY department_id DESC,
salary ;
结果:
3、查询员工表的job_id中包含a和e的,并且a在e的前面
SELECT
job_id
FROM
employees
WHERE job_id LIKE "%a%e%" ;
结果:
4、已知表student,里面有id(学号),NAME,gradeId(年级编号)
已知表grade,里面有id(年级编号),NAME(年级名)
已知表result,里面有id,score,studentNo(学号)
要求查询姓名、年级名、成绩
SELECT
s.name,
g.name,
r.score
FROM
student s,
grade g,
result r
WHERE s.id = r.studentNO
AND s.gradeID = g.id ;
5、显示当前日期,以及去前后空格,截取子字符串的函数
SELECT NOW()
SELECT TRIM(" aa ")
SELECT SUBSTR("aaaa",2,4)