10_子查询
一、子查询
将一条完成的查询语句作为另一个查询语句的一部分
--谁的工资比 Abel 高
select * from employees where salary >(
select salary from employees where last_name = 'Abel');
二、子查询语法
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list
FROM table);
- 子查询 (内查询) 在主查询之前一次执行完成。
- 子查询的结果被主查询(外查询)使用 。
注意事项:
- 子查询要包含在括号内。
- 将子查询放在比较条件的右侧。
- 单行操作符对应单行子查询,多行操作符对应多行子查询。
三、子查询类型
select * from employees
where salary =(select min(salary) from employees)
and
hire_date =(select min(hire_date) from employees);
-- 查询 工资低于平均工资的雇员信息
select * from employees
where salary <
(select avg(salary) from employees);
select * from employees
where department_id in
(select department_id from departments where location_id = 1700);
1.单行子查询
只返回一行。
使用单行比较操作符。
--题目:返回job_id与141号员工相同,salary比143号员工多的
--员工 姓名,job_id 和工资
select first_name,last_name,job_id,salary
from employees
where job_id = (select job_id from employees where employee_id =141)
and salary > (select salary from employees where employee_id =143)
1.1.在子查询中使用组函数
题目:返回公司工资最少的员工的last_name,job_id和salary
--返回公司工资最少的员工的last_name,job_id和salary
select last_name,job_id,salary
from employees
where salary = (select min(salary) from employees);
1.2.子查询中的 HAVING 子句
首先执行子查询。
向主查询中的HAVING 子句返回结果
题目:查询最低工资大于50号部门最低工资的部门id和其最低工资
--题目:查询最低工资大于50号部门最低工资的部门id和其最低工资
select department_id,min(salary)
from employees
group by department_id
having min(salary) > (select min(salary) from employees where department_id =50);
2.非法使用子查询
SELECT employee_id, last_name
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees
GROUP BY department_id);
多行子查询使用单行比较符
3.子查询中的空值问题
SELECT last_name, job_id
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE last_name = 'Haas');
子查询不返回任何行
4.多行子查询
返回多行。
使用多行比较操作符。
4.1.在多行子查询中使用 ANY 操作符
ANY 小于子查询中的任意一个
--题目:返回其它部门中比job_id为‘IT_PROG’部门任一工资低的
--员工的员工号、姓名、job_id 以及salary
select employee_id,last_name,job_id,salary
from employees
where salary < any(
select salary from employees where job_id ='IT_PROG')
4.2.在多行子查询中使用 ALL 操作符
ALL 小于所有的 那就是比最小的还小
扫描二维码关注公众号,回复:
10419927 查看本文章
select employee_id,last_name,job_id,salary
from employees
where salary < ALL(
select salary from employees where job_id ='IT_PROG')
4.3.子查询中的空值问题
SELECT emp.last_name
FROM employees emp
WHERE emp.employee_id NOT IN
(SELECT mgr.manager_id
FROM employees mgr);
--no rows selected
当主查询中匹配条件中有空值时 如果子查询中也返回的有空值 空值也是可以匹配的
四、分页查询
数据伪列:指的是表中不存在但却有可以直接使用的列,在oracle中除了SYSDATE外还存着有ROWNUM、ROWID连个与行记录有关的伪列
虚拟表 dual 可以用来测试函数或一般的运算
1.ROWNUM
行号:ROWNUM 查询数据时,可以使用ROWNUM这个伪列,动态的生成行记录的编号。
ROWNUM不是固定的,而是动态生成的。
--rownum 是一个数据伪列 不存在 但可以直接使用的列
--rownum 自动生成 与数据无关 在每次的查询中总是从1开始
--显示前20行记录
select rownum ,employee_id,first_name ,last_name from employees where rownum <= 20 ;
分页查询
--显示11 - 20 条记录 现在每页显示10记 录 显示第二页 11 -20
select * from (
select rownum r ,employee_id,first_name ,last_name from employees where rownum <= 20 ) temp
where temp.r >10;
--显示11 - 20 条记录 现在每页显示10记 录 显示第二页 11 -20
select * from (
select rownum r ,employee_id,first_name ,last_name from employees where rownum <= 30 ) temp
where temp.r >20;
总记录数:total = 107 查出来的
每页显示的条数:pageSize= 10 这个一般是固定的,但是也可以改变
总页数:page = 107/10+1 = 11 计算出来的
当前页数:currentPage 有用户决定的
分页的语法:
select * from (
select rownum r ,employee_id,first_name ,last_name from employees where rownum <= '结束的rounum' ) temp
where temp.r >‘开始的rownum’;
结束的rounum = currentPage(1) *10;
开始的rownum=(currentPage - 1) * 10
select * from (
select rownum r ,employee_id,first_name ,last_name from employees where rownum <= '结束的rounum' ) temp
where temp.r >=‘开始的rownum’;
结束的rounum = currentPage(1) *10;
开始的rownum=(currentPage - 1) * 10 + 1
mysql的分页:limit 当前开始的记录数 每页显示的条数
sqlserver:top
2.ROWID
对查询的结果进行更新
SELECT * FROM employees for update;
--rowid 为每一条记录生成一个唯一的行标识 18位的16进制数
select rowid ,employee_id,first_name ,last_name from employees;
--列出受雇日期早于其直接上级的所有员工的编号,姓名,部门名称,上级的姓名
select e.employee_id ,e.last_name, e.hire_date ,d .department_name,m.last_name,m.hire_date
from employees e,departments d,employees m
where e.department_id = d.department_id and e.manager_id = m.employee_id
and e.hire_date < m.hire_date;