#子查询
#需求:谁的工资比Abel的高!
#方法1:
SELECT salary
from employees
WHERE last_name='Abel';
SELECT last_name, salary
FROM employees
WHERE salary>11000;
#方式2:自连接
SELECT e2.last_name,e2.salary
FROM employees e1,employees e2
WHERE e2.salary>e1.salary #多表连接条件
AND e1.last_name='Abel';
#方式3:子查询
SELECT last_name, salary
FROM employees
WHERE salary>(
SELECT salary
from employees
WHERE last_name='Abel'
);
#称谓的规范:分为外查询(或主查询)、内查询(或子查询)
/*
子查询(或内查询)在主查询之前一次执行完成
子查询的结果被主查询(或外查询)使用
注意事项:子查询要包含在括号内
将子查询放在比较条件的右侧
单行操作符对应单行子查询,多行操作符对应多行子查询
*/
SELECT last_name, salary
FROM employees
WHERE (
SELECT salary
from employees
WHERE last_name='Abel'
)
/*
子查询的分类
角度一:从内查询返回的结果条目数
单行子查询 vs 多行子查询 (工资大于6000的姓名)
角度二: 内查询是否被执行多
相关子查询 vs 不相关子查询
如:
相关子查询的需求:查询工资大于本部门平均工资的员工信息
不相关子查询的需求:查询工资大于本公司平均工资的员工信息
*/
#单行子查询
#单行子查询操作符:= != <> > >= <=
#习题:查询工资大于149号员工工资的员工信息
SELECT employee_id,last_name,salary
FROM employees
WHERE salary >(
SELECT salary
FROM employees
WHERE employee_id = 149
);
#习题:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
SELECT last_name,job_id,salary,job_id
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. 从里往外写
2. 从外往里写
*/
#中英文互换
#习题:返回工资最少的员工的last_name,job_id和salary
SELECT last_name,job_id,salary
FROM employees
WHERE salary=(
SELECT MIN(salary)
from employees
);
#习题:查询与141号员工的manger_id和department_id相同的employee_id,manger_id和department_id
SELECT employee_id,manager_id,department_id
FROM employees
WHERE manager_id =(
SELECT manager_id
FROM employees
WHERE employee_id=141
)
AND department_id =(
SELECT department_id
FROM employees
WHERE employee_id=141
)
AND employee_id!=141;
SELECT employee_id,manager_id,department_id
FROM employees
WHERE (manager_id,department_id) =(
SELECT manager_id,department_id
FROM employees
WHERE employee_id=141
)
AND employee_id!=141;
#习题:查询最低工资大于110号部门最低部门最低工资的部门id和其最低工资
SELECT department_id,MIN(salary)
FROM employees
GROUP BY department_id
HAVING min(salary)>(
SELECT MIN(salary)
FROM employees
WHERE department_id=60
)
AND department_id is not null;
#非法使用子查询
SELECT employee_id,last_name
FROM employees
WHERE salary=(
SELECT MIN(salary)
FROM employees
GROUP BY department_id
);
#多行子查询
/*
也称为集合比较子查询
内查询返回多行
使用多行比较操作符
*/
#多行比较操作符
/*
IN 等于列表中的任意一个
ANY 需要和单行比较操作符一起使用,和子查询返回的某一个值比较(任一)
ALL 需要和单行比较操作符一起使用,和子查询返回的所有值比较
SOME实际上ANY的别名,作用相同,一般常用ANY
*/
SELECT employee_id,last_name
FROM employees
WHERE salary =(
SELECT MIN(salary)
FROM employees
GROUP BY department_id
);
#ANY/ALL
#习题:返回其他job_id中比job_id为'IT_PROG'部门任一工资低的员工的员工号、姓名、job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE job_id <>'IT_PROG'
AND salary from employees
WHERE job_id='IT_PROG'
);
#习题:返回公司工资最少的员工的last_name,job_id,和salary
SELECT last_name,job_id,salary
FROM employees
HAVING salary=all(SELECT MIN(salary)
FROM employees
);
#习题:查询与141号员工的manager_id 和 department_id相同的其他员工的employee_id,manager_id,department_id
SELECT employee_id,manager_id,department_id
FROM employees
WHERE manager_id=(SELECT manager_id
FROM employees
WHERE employees=141
);
#习题:查询平均工资最低的部门id
SELECT department_id
FROM employees
WHERE salary=ALL(
SELECT AVG(salary) avg_sal
FROM employees
GROUP BY department_id
);
#mysql中聚合函数不能嵌套
SELECT MIN(AVG(salary))
FROM employees
GROUP BY department_id;
#第九章 约束
/*
1.基础知识
1.1 为什么要约束? 是为了保证数据的完整性
1.2 什么叫约束? 对表中字符的限制
1.3 约束的分类
角度1:约束的子段的个数
单列约束 vs 多列约束
角度2: 约束的作用范围
列级约束:将此约束声明在对应字段的后面
表级约束:在表中所有字段都声明完,在所有字段后面声明约束
角度3:约束的作用或(功能)
(1)NOT NULL 非空约束
(2)UNIQUE 唯一性约束
(3)PRIMARY KEY 主键约束
(4)FOREIGN KEY 外键约束
(5)CHECK 检查约束
(6)DEFAULT 默认值约束
1.4 如何添加/删除约束
CREATE TABLE 时添加约束
ALTER TABLE 时增加、删除约束
*/
#如何查看表中的约束
SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';
# NOT NULL (非空约束)只能用列级约束不能表级约束
CREATE DATABASE wajjj;
USE wajjj;
#3.1 在CREATE TABLE 时添加约束
CREATE TABLE test1(
id INT not NULL,
last_name VARCHAR(10) NOT NULL,
email VARCHAR(10),
salary INT
);
desc test1;