上次整理了一些练习发到博客上了,也说要发基础的,整理了一下午才算是把查询那块的勉强整理完,下次再整理其他的,另外还在写设计模式和数据结构的草稿,写的差不多会慢慢发的,这两项算是副线发展,主线还是按JavaSE–JavaWeb–JavaEE的方向来。因为Java后面都需要数据库,所以就先把数据库先抽空写出来,要成体系嘛,我也会坚持的哈。废话不说了,进入主题吧。


关于查询所需要的表,直接将表贴到这里供大家参考。

employees表:

departments表:

job_grades表:

jobs表:

locations表:


第1章:SQL概述

SQL:Structured Query Language结构化查询语言,它是使用关系模型的数据库应用语言。

1. SQL的语言规范

  • mysql对于SQL语句不区分大小写,SQL语句关键字尽量大写。
  • SQL 可以写在一行或者多行。为了提高可读性,各子句分行写,必要时使用缩进。
  • 关键字不能被缩写也不能分行。
  • 值,除了数值型,字符串型和日期时间类型使用单引号(’ ')
  • 别名,尽量使用双引号(" "),而且不建议省略as。
  • 所有标点符号使用英文状态下的半角输入方式。
  • 必须保证所有(),单引号,双引号是成对结束的。
  • 可以使用(1)#单行注释 (2)–空格单行注释 (3)/* 多行注释 */。

2. 命名规则

  • 数据库、表名不得超过30个字符,变量名限制为29个。
  • 必须只能包含 A–Z, a–z, 0–9, _共63个字符。
  • 不能在对象名的字符间留空格。
  • 必须不能和用户定义的其他对象重名。
  • 必须保证你的字段没有和保留字、数据库系统或常用方法冲突。
  • 保持字段名和类型的一致性,在命名字段并为其指定数据类型的时候一定要保证一致性。假如数据类型在一个表里是整数,那在另一个表里可就别变成字符型了。

说明:一个语句可以分开多行编写,以;或\g结束

3. SQL分类

  • DDL(Data Definition Languages):数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象。

    • 主要的语句关键字包括CREATEDROPALTER等。
  • DML(Data Manipulation Language):数据操作语言,用于添加、删除、更新和查询数据库记录,并检查数据完整性。

    • 主要的语句关键字包括INSERTDELETEUPDATESELECT等。
    • SELECT是SQL语言的基础,最为重要。
  • DCL(Data Control Language):数据控制语言,用于控制不同数据段直接的许可和访问级别的语句。这些语句定义了数据库、表、字段、用户的访问权限和安全级别。

    • 主要的语句关键字包括GRANTREVOKECOMMITROLLBACKSAVEPOINT等。

下面主要说的是DML中的select,关于其他的下篇博客会介绍到。


第2章:数据处理之查询

2.1 基本的SELECT语句

2.1.1 SELECT … FROM

SELECT   标识选择哪些列
FROM     标识从哪个表中选择
  • 选择全部列:
SELECT *
FROM   departments;

  • 选择特定的列:
SELECT department_id, location_id
FROM   departments;


2.1.2 列的别名

  • 重命名一个列

  • 便于计算

  • 紧跟列名,也可以在列名和别名之间加入关键字AS,别名使用双引号,以便在别名中包含空格或特殊的字符并区分大小写。

使用别名

SELECT last_name AS name, commission_pct comm
FROM   employees;

SELECT last_name "Name", salary*12 "Annual Salary"
FROM   employees;

2.1.3 去除重复行

默认情况下,查询会返回全部行,包括重复行。

SELECT department_id
FROM   employees;

在SELECT语句中使用关键字DISTINCT去除重复行。

SELECT DISTINCT department_id
FROM   employees;


2.1.4 空值参与运算

  • 所有运算符或列值遇到null值,运算的结果都为null
SELECT employee_id,salary,commission_pct,
12 * salary * (1 + commission_pct) "annual_sal"
FROM employees;


2.1.5 显示表结构

使用DESCRIBE 或 DESC 命令,表示表结构。

DESCRIBE employees;

2.2 过滤数据

2.2.1 SELECT … FROM … WHERE

  • 使用WHERE 子句,将不满足条件的行过滤掉
  • WHERE子句紧随 FROM子句
#选择department_id=90的员工信息
SELECT employee_id, last_name, job_id, department_id
FROM   employees
WHERE  department_id = 90 ;

2.2.2 比较运算符

① 基本操作符
操作符 含义
= 等于(不是==)
> 大于
>= 大于、等于
< 小于
<= 小于、等于
<> 或 != 不等于

说明:赋值符号使用 :=

#选择工资小于等于3000的员工姓名和工资
SELECT last_name, salary
FROM   employees
WHERE  salary <= 3000;

② 其它比较运算符
操作符 含义
BETWEEN … AND 在两个值之间(包含边界)
IN(set) 等于值列表中的一个
LIKE 模糊查询
IS NULL 空值

1)BETWEEN … AND

使用 BETWEEN 运算来显示在一个区间内的值

SELECT last_name, salary
FROM   employees
WHERE  salary BETWEEN 2500 AND 3500;

2)IN

使用 IN运算显示列表中的值。

#选择管理Id为100,101,201的员工信息
SELECT employee_id, last_name, salary, manager_id
FROM   employees
WHERE  manager_id IN (100, 101, 201);



3)LIKE

  • 使用 LIKE 运算选择类似的值

  • 选择条件可以包含字符或数字:

    • % 代表零个或多个字符(任意个字符)
    • _ 代表一个字符
#选择first_name第一个字母为S的first_name
SELECT  first_name
FROM    employees
WHERE   first_name LIKE 'S%';

  • ‘%’和‘_’可以同时使用。
#第二个字母为o的last_name
SELECT last_name
FROM   employees
WHERE  last_name LIKE '_o%';

ESCAPE

  • 回避特殊符号的:使用转义符。例如:将[%]转为[ %]、[]转为[ ],然后再加上[ESCAPE‘$’]即可。
SELECT job_id
FROM   jobs
WHERE  job_id LIKE ‘IT\_%‘;

如果使用\表示转义,要省略ESCAPE。如果不是\,则要加上ESCAPE。

SELECT job_id
FROM   jobs
WHERE  job_id LIKE ‘IT$_%‘ escape ‘$‘;

4)NULL

使用 IS (NOT) NULL 判断空值。

#选择manager_id为NULL的员工的last_name,manager_id
SELECT last_name, manager_id
FROM   employees
WHERE  manager_id IS NULL;

2.2.3 逻辑运算符

操作符 含义
&& (或AND) 逻辑且
||(或OR) 逻辑或
NOT 逻辑否
XOR 逻辑异或

1)&& (或AND)

AND要求并的关系为真。

#查询金额大于等于10000并且job_id中有MAN字段的员工信息
SELECT employee_id, last_name, job_id, salary
FROM   employees
WHERE  salary >=10000
AND    job_id LIKE '%MAN%';

2)||(或OR)

OR要求或关系为真。

##查询金额大于等于10000或者job_id中有MAN字段的员工信息
SELECT employee_id, last_name, job_id, salary
FROM   employees
WHERE  salary >= 10000
OR     job_id LIKE '%MAN%';

3)NOT

#查询不在IT_PROG,'ST_CLERK,SA_REP'部门的员工的last_name和job_id
SELECT last_name, job_id
FROM   employees
WHERE  job_id NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP');

4)XOR

select last_name,department_id,salary
from employees
where department_id in (10,20) XOR salary > 8000;

2.2.4 算术运算符

运算符 说明
+ 加法
- 减法
* 乘法
/ (或div) 除法
%(或mod) 取模
#查询部门id%2等于0的员工信息
SELECT employee_id,salary,department_id
FROM employees
WHERE department_id MOD 2 = 0;

2.3 排序数据和分页

2.3.1 排序数据

  • 使用 ORDER BY 子句排序

    • ASC(ascend): 升序
    • DESC(descend):降序
  • ORDER BY 子句在SELECT语句的结尾。

#查询按金额升序排序的员工信息
SELECT employee_id, last_name, salary
FROM   employees
ORDER BY salary;

#查询按部门id升序排列,相同则按金额降序排列的员工信息。
SELECT last_name, department_id, salary
FROM   employees
ORDER BY department_id, salary DESC;

  • 可以使用不在SELECT列表中的列排序。

2.3.2 分页

  • MySQL中使用limit实现分页
    所谓分页显示,就是将数据库中的结果集,一段一段显示出来需要的条件。
--前10条记录:
SELECT * FROM table LIMIT 0,10;--第11至20条记录:
SELECT * FROM table LIMIT 10,10;--第21至30条记录:
SELECT * FROM table LIMIT 20,10;
  • 公式**:(当前页数-1)每页条数,每页条数*
SELECT * FROM table
LIMIT(PageNo - 1)*PageSize,PageSize;
  • 注意:limit子句必须放在整个查询语句的最后!

2.4 多表查询

2.4.1 MySQL连接

使用连接在多个表中查询数据。

SELECT   table1.column, table2.column
FROM    table1, table2
WHERE   table1.column1 = table2.column2;
  • 在 WHERE子句中写入连接条件。

  • 在表中有相同列时,在列名之前加上表名前缀。

2.4.2 等值连接

SELECT employees.employee_id, employees.last_name, employees.department_id, departments.department_id,departments.location_id
FROM   employees, departments
WHERE  employees.department_id = departments.department_id;

多个连接条件用 AND 操作符

区分重复的列名

  • 使用表名前缀在多个表中区分相同的列

  • 在不同表中具有相同列名的列可以用表的别名加以区分。

表的别名

  • 使用别名可以简化查询。

  • 使用表名前缀可以提高执行效率。

SELECT e.employee_id, e.last_name, e.department_id,d.department_id, d.location_id
FROM   employees e , departments d
WHERE  e.department_id = d.department_id;

连接多个表
连接 n个表,至少需要n-1个连接条件。
例如:连接三个表,至少需要两个连接条件。
查询出公司员工的 last_name,department_name, city

SELECT last_name,department_name,city
FROM   employees e , departments d,locations l
WHERE  e.department_id = d.department_id
AND d.location_id = l.location_id

2.4.3 自连接 vs 非自连接

  • 当两张表是同一张表,只是用取别名的方式虚拟成两张表以代表不同的意义。然后两个表再进行内连接,外连接等查询

题目:查询employees表,返回“Xxx works for Xxx”

SELECT CONCAT(worker.last_name ,' works for ' , manager.last_name)
FROM   employees worker, employees manager
WHERE  worker.manager_id = manager.employee_id ;

2.4.4 分类3:内连接 vs 外连接

  • 内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行

  • 外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。

① SQL99:使用ON子句创建连接
  • 自然连接中是以具有相同名字的列为连接条件的。

  • 可以使用 ON 子句指定额外的连接条件

  • 这个连接条件是与其它条件分开的。

  • ON 子句使语句具有更高的易读性

SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id
FROM   employees e JOIN departments d
ON     (e.department_id = d.department_id);

SELECT employee_id, city, department_name
FROM   employees e
JOIN   departments d
ON     d.department_id = e.department_id
JOIN   locations l
ON     d.location_id = l.location_id;

② 左外连接
SELECT e.last_name, e.department_id, d.department_name
FROM   employees e
LEFT OUTER JOIN departments d
ON   (e.department_id = d.department_id) ;


③ 右外连接
SELECT e.last_name, e.department_id, d.department_name
FROM   employees e
RIGHT OUTER JOIN departments d
ON    (e.department_id = d.department_id) ;

总结:SQL JOINS

补充:

UNION操作符

UNION 操作符返回两个查询的结果集的并集。

UNION ALL操作符

UNION ALL操作符返回两个查询的结果集的并集。对于两个结果集的重复部分,不去重。

2.5 单行函数

2.5.1 介绍

两种SQL函数

单行函数

  • 操作数据对象

  • 接受参数返回一个结果

  • 只对一行进行变换

  • 每行返回一个结果

  • 可以嵌套

  • 参数可以是一列或一个值

2.5.2 字符串函数

函数 用法
CONCAT(S1,S2,…,Sn) 连接S1,S2,…,Sn为一个字符串
CONCAT_WS(s, S1,S2,…,Sn) 同CONCAT(s1,s2,…)函数,但是每个字符串之间要加上s
CHAR_LENGTH(s) 返回字符串s的字符数
LENGTH(s) 返回字符串s的字节数,和字符集有关
INSERT(str, index , len, instr) 将字符串str从第index位置开始,len个字符长的子串替换为字符串instr
UPPER(s) 或 UCASE(s) 将字符串s的所有字母转成大写字母
LOWER(s) 或LCASE(s) 将字符串s的所有字母转成小写字母
LEFT(s,n) 返回字符串s最左边的n个字符
RIGHT(s,n) 返回字符串s最右边的n个字符
LPAD(str, len, pad) 用字符串pad对str最左边进行填充,直到str的长度为len个字符
RPAD(str ,len, pad) 用字符串pad对str最右边进行填充,直到str的长度为len个字符
LTRIM(s) 去掉字符串s左侧的空格
RTRIM(s) 去掉字符串s右侧的空格
TRIM(s) 去掉字符串s开始与结尾的空格
TRIM(【BOTH 】s1 FROM s) 去掉字符串s开始与结尾的s1
TRIM(LEADING s1 FROM s) 去掉字符串s开始处的s1
TRIM(TRAILING s1 FROM s) 去掉字符串s结尾处的s1
REPEAT(str, n) 返回str重复n次的结果
REPLACE(str, a, b) 用字符串b替换字符串str中所有出现的字符串a
STRCMP(s1,s2) 比较字符串s1,s2
SUBSTRING(s,index,len) 返回从字符串s的index位置其len个字符
  • 举例1:大小写控制函数
函数 结果
LOWER(‘SQL Course’) sql course
UPPER(‘SQL Course’) SQL COURSE

这类函数改变字符的大小写。

  • 举例2:字符控制函数
函数 结果
CONCAT(‘Hello’,‘World’) HelloWorld
SUBSTR(‘HelloWorld’,1,5) Hello
LENGTH(‘HelloWorld’) 10
INSTR(‘HelloWorld’,‘W’) 6
LPAD(salary,10,’*’) *****24000
RPAD(salary,10, ‘*’) 24000*****
TRIM(‘H’ FROM ‘HelloWorld’) elloWorld
REPLACE(‘abcd’,‘b’,‘m’) amcd

2.5.3 数值函数

函数 用法
ABS(x) 返回x的绝对值
CEIL(x) 返回大于x的最小整数值
FLOOR(x) 返回小于x的最大整数值
MOD(x,y) 返回x/y的模
RAND() 返回0~1的随机值
ROUND(x,y) 返回参数x的四舍五入的有y位的小数的值
TRUNCATE(x,y) 返回数字x截断为y位小数的结果
SQRT(x) 返回x的平方根
POW(x,y) 返回x的y次方
  • 举例1:ROUND:四舍五入
ROUND(45.926, 2)     -->  45.93
  • 举例2:TRUNCATE:截断
TRUNCATE(45.926)      --> 45
  • 举例3:MOD:求余
MOD(1600, 300)    --> 100

2.5.4 日期函数

函数 用法
CURDATE() 或 CURRENT_DATE() 返回当前日期
CURTIME() 或 CURRENT_TIME() 返回当前时间
NOW() / SYSDATE() / CURRENT_TIMESTAMP() / LOCALTIME() / LOCALTIMESTAMP() 返回当前系统日期时间
YEAR(date) / MONTH(date) / DAY(date) / HOUR(time) / MINUTE(time) / SECOND(time) 返回具体的时间值
WEEK(date) / WEEKOFYEAR(date) 返回一年中的第几周
DAYOFWEEK() 返回周几,注意:周日是1,周一是2,。。。周六是7
WEEKDAY(date) 返回周几,注意,周1是0,周2是1,。。。周日是6
DAYNAME(date) 返回星期:MONDAY,TUESDAY…SUNDAY
MONTHNAME(date) 返回月份:January,。。。。。
DATEDIFF(date1,date2) / TIMEDIFF(time1, time2) 返回date1 - date2的日期间隔 / 返回time1 - time2的时间间隔
DATE_ADD(datetime, INTERVAL expr type) 返回与给定日期时间相差INTERVAL时间段的日期时间
DATE_FORMAT(datetime ,fmt) 按照字符串fmt格式化日期datetime值
STR_TO_DATE(str, fmt) 按照字符串fmt对str进行解析,解析为一个日期

其中:

(1)DATE_ADD(datetime,INTERVAL expr type)

表达式类型:

参数类型 参数类型
YEAR YEAR_MONTH
MONTH DAY_HOUR
DAY DAY_MINUTE
HOUR DAY_SECOND
MINUTE HOUR_MINUTE
SECOND HOUR_SECOND
MINUTE_SECOND

举例:

SELECT DATE_ADD(NOW(), INTERVAL 1 YEAR);
SELECT DATE_ADD(NOW(), INTERVAL -1 YEAR);   #可以是负数
SELECT DATE_ADD(NOW(), INTERVAL '1_1' YEAR_MONTH);   #需要单引号

(2)DATE_FORMAT(datetime,fmt) 和 STR_TO_DATE(str, fmt)

格式符 说明 格式符 说明
%Y 4位数字表示年份 %y 表示两位数字表示年份
%M 月名表示月份(January,…) %m 两位数字表示月份(01,02,03。。。)
%b 缩写的月名(Jan.,Feb.,…) %c 数字表示月份(1,2,3,…)
%D 英文后缀表示月中的天数(1st,2nd,3rd,…) %d 两位数字表示月中的天数(01,02…)
%e 数字形式表示月中的天数(1,2,3,4,5…)
%H 两位数字表示小数,24小时制(01,02…) %h和%I 两位数字表示小时,12小时制(01,02…)
%k 数字形式的小时,24小时制(1,2,3) %l 数字形式表示小时,12小时制(1,2,3,4…)
%i 两位数字表示分钟(00,01,02) %S和%s 两位数字表示秒(00,01,02…)
%W 一周中的星期名称(Sunday…) %a 一周中的星期缩写(Sun.,Mon.,Tues.,…)
%w 以数字表示周中的天数(0=Sunday,1=Monday…)
%j 以3位数字表示年中的天数(001,002…) %U 以数字表示年中的第几周,(1,2,3。。)其中Sunday为周中第一天
%u 以数字表示年中的第几周,(1,2,3。。)其中Monday为周中第一天
%T 24小时制 %r 12小时制
%p AM或PM %% 表示%

2.5.5 流程函数

函数 用法
IF(value,t ,f) 如果value是真,返回t,否则返回f
IFNULL(value1, value2) 如果value1不为空,返回value1,否则返回value2
CASE WHEN 条件1 THEN result1 WHEN 条件2 THEN result2 … [ELSE resultn] END 相当于Java的if…else if…else…
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN 值1 … [ELSE 值n] END 相当于Java的switch…case…
SELECT employee_id,salary, CASE WHEN salary>=15000 THEN '高薪' WHEN salary>=10000 THEN '潜力股'  WHEN salary>=8000 THEN '屌丝' ELSE '草根' END  "描述"
FROM employees;
SELECT oid,`status`, CASE `status` WHEN 1 THEN '未付款' WHEN 2 THEN '已付款' WHEN 3 THEN '已发货'  WHEN 4 THEN '确认收货'  ELSE '无效订单' END
FROM t_order;
  • 举例1:
SELECT employee_id,12 * salary * (1 + IFNULL(commission_pct,0))
FROM employees;
  • 举例2:
SELECT last_name, job_id, salary,CASE job_id WHEN 'IT_PROG'  THEN  1.10*salaryWHEN 'ST_CLERK' THEN  1.15*salaryWHEN 'SA_REP'   THEN  1.20*salaryELSE      salary END     "REVISED_SALARY"
FROM   employees;

2.5.6 其他函数

函数 用法
database() 返回当前数据库名
version() 返回当前数据库版本
user() 返回当前登录用户名
password(str) 返回字符串str的加密版本,41位长的字符串
md5(str) 返回字符串str的md5值,也是一种加密方式

2.6 分组函数

2.6.1 组函数介绍

  • 什么是分组函数

分组函数作用于一组数据,并对一组数据返回一个值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mkacU4ZN-1571548409205)(SQL开发.assets/1554980924940.png)]

  • 组函数类型

    • AVG()
    • SUM()
    • MAX()
    • MIN()
    • COUNT()

2.6.2 AVG和SUM函数

可以对数值型数据使用AVG 和 SUM 函数。

#查询job_id中有REP字符串的员工工资的平均值、最大值、最小值、总数
SELECT AVG(salary), MAX(salary),MIN(salary), SUM(salary)
FROM   employees
WHERE  job_id LIKE '%REP%';

2.6.3 MIN和MAX函数

可以对任意数据类型的数据使用 MIN 和 MAX 函数。

SELECT MIN(salary), MAX(salary)
FROM employees;

2.6.4 COUNT函数

COUNT(*)返回表中记录总数,适用于任意数据类型

SELECT COUNT(*)
FROM      employees
WHERE  department_id = 50;


•COUNT(expr) 返回expr不为空的记录总数。

SELECT COUNT(salary)
FROM   employees
WHERE  department_id = 50;

  • 问题:用count(*),count(1)谁好呢?

    其实,对于myisam引擎的表是没有区别的。这种引擎内部有一计数器在维护着行数。

    Innodb引擎的表用count(*)直接读行数,效率很低,因为innodb真的要去数一遍。

2.6.5 GROUP BY

可以使用GROUP BY子句将表中的数据分成若干组

SELECT column, group_function(column)
FROM table
[WHERE  condition]
[GROUP BY   group_by_expression]
[ORDER BY   column];

明确:WHERE一定放在FROM后面

在SELECT列表中所有未包含在组函数中的列都应该包含在 GROUP BY子句中

SELECT   department_id, AVG(salary)
FROM     employees
GROUP BY department_id ;

包含在 GROUP BY 子句中的列不必包含在SELECT 列表中

SELECT   AVG(salary)
FROM     employees
GROUP BY department_id ;

使用多个列分组

SELECT   department_id dept_id, job_id, SUM(salary)
FROM     employees
GROUP BY department_id, job_id ;


2.6.6 HAVING

  • 非法使用组函数

    • 不能在 WHERE 子句中使用组函数。
    • 可以在 HAVING 子句中使用组函数。
SELECT   department_id, AVG(salary)
FROM     employees
WHERE    AVG(salary) > 8000
GROUP BY department_id;

过滤分组:HAVING子句

  1. 行已经被分组。
  2. 使用了组函数。
  3. 满足HAVING 子句中条件的分组将被显示。
SELECT   department_id, MAX(salary)
FROM     employees
GROUP BY department_id
HAVING   MAX(salary)>10000 ;

第3章:子查询

3.1 基本介绍

  • 子查询 (内查询) 在主查询之前一次执行完成。

  • 子查询的结果被主查询(外查询)使用 。

  • 子查询的类型:

    • 单行子查询

    • 多行子查询

  • 注意事项

    • 子查询要包含在括号内.
    • 将子查询放在比较条件的右侧.
    • 单行操作符对应单行子查询,多行操作符对应多行子查询.

3.2 单行子查询

3.2.1 单行比较操作符

操作符 含义
= equal to
> greater than
>= greater than or equal to
< less than
<= less than or equal to
<> not equal to
SELECT last_name
FROM   employees
WHERE  salary >(SELECT salaryFROM   employeesWHERE  last_name = 'Abel');

题目:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资

SELECT last_name, job_id, salary
FROM   employees
WHERE  job_id =  (SELECT job_idFROM   employeesWHERE  employee_id = 141)
AND    salary >(SELECT salaryFROM   employeesWHERE  employee_id = 143);

题目:返回公司工资最少的员工的last_name,job_id和salary

SELECT last_name, job_id, salary
FROM   employees
WHERE  salary = (SELECT MIN(salary)FROM   employees);

3.2.2 子查询中的 HAVING 子句

  • 首先执行子查询。
  • 向主查询中的HAVING 子句返回结果。

题目:查询最低工资大于50号部门最低工资的部门id和其最低工资

SELECT   department_id, MIN(salary)
FROM     employees
GROUP BY department_id
HAVING   MIN(salary) >(SELECT MIN(salary)FROM   employeesWHERE  department_id = 50);

3.2.3 子查询中的空值问题

SELECT last_name, job_id
FROM   employees
WHERE  job_id =(SELECT job_idFROM   employeesWHERE  last_name = 'Haas');

=

子查询不返回任何行

3.2.4 非法使用子查询

SELECT employee_id, last_name
FROM   employees
WHERE  salary =(SELECT   MIN(salary)FROM     employeesGROUP BY department_id);

多行子查询使用单行比较符

3.2 多行子查询

  • 返回多行。

  • 使用多行比较操作符。

操作符 含义
IN 等于列表中的任意一个
ANY 和子查询返回的某一个值比较
ALL 和子查询返回的所有值比较

体会any和all的区别

3.2.1 使用ANY或ALL操作符

题目:返回其它job_id中比job_id为‘IT_PROG’部门任一工资低的员工的员工号、姓名、job_id 以及salary

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ANY (SELECT salaryFROM employeesWHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';

题目:返回其它job_id中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id以及salary

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary < ALL (SELECT salaryFROM employeesWHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';


3.3 相关子查询

相关子查询按照一行接一行的顺序执行,主查询的每一行都执行一次子查询。

题目:查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id
方式一:相关子查询

SELECT last_name,salary,department_id
FROM employees outers
WHERE salary > (SELECT AVG(salary)FROM employeesWHERE department_id=outers.`department_id`)

方式二:在from中使用子查询

SELECT last_name,salary,e1.department_id
FROM employees e1,(SELECT department_id,AVG(salary) dept_avg_sal FROM employees GROUP BY department_id) e2
WHERE e1.`department_id` = e2.department_id
AND e2.dept_avg_sal < e1.`salary`;

题目:查询员工的id,salary,按照department_name 排序

SELECT employee_id,salary
FROM employees e
ORDER BY (SELECT department_nameFROM departments dWHERE e.`department_id` = d.`department_id`);

3.4 EXISTS操作符

  • EXISTS 操作符检查在子查询中是否存在满足条件的行

  • 如果在子查询中存在满足条件的行:

    • 不在子查询中继续查找
    • 条件返回 TRUE
  • 如果在子查询中不存在满足条件的行:

    • 条件返回 FALSE
    • 继续在子查询中查找

题目:查询公司管理者的employee_id,last_name,job_id,department_id信息

方式一:

SELECT employee_id, last_name, job_id, department_id
FROM   employees e1
WHERE  EXISTS ( SELECT 'X'FROM   employees e2WHERE  e2.manager_id = e1.employee_id);

方式二:

SELECT DISTINCT e1.employee_id, e1.last_name, e1.job_id, e1.department_id
FROM   employees e1 JOIN employees e2
WHERE e1.employee_id = e2.manager_id;

方式三:

SELECT employee_id,last_name,job_id,department_id
FROM employees
WHERE employee_id IN (SELECT DISTINCT manager_idFROM employees);

题目:查询departments表中,不存在于employees表中的部门的department_id和department_name

SELECT department_id, department_name
FROM departments d
WHERE NOT EXISTS (SELECT 'X'FROM   employeesWHERE  department_id = d.department_id);

3.5 相关更新

UPDATE table1 alias1
SET    column = (SELECT expressionFROM   table2 alias2WHERE  alias1.column = alias2.column);

使用相关子查询依据一个表中的数据更新另一个表的数据。

练习:

1)
ALTER TABLE employees
ADD(department_name VARCHAR2(14));
2)
UPDATE employees e
SET    department_name =  (SELECT department_name FROM   departments dWHERE  e.department_id = d.department_id);

3.6 相关删除

 DELETE FROM table1 alias1WHERE column operator (SELECT expressionFROM   table2 alias2WHERE  alias1.column = alias2.column);

使用相关子查询依据一个表中的数据删除另一个表的数据

题目:删除表employees中,其与emp_history表皆有的数据

DELETE FROM employees e
WHERE employee_id in  (SELECT employee_idFROM   emp_history WHERE  employee_id = e.employee_id);


今天就先到这,查询这块的内容也差不多说完了。其它的下次再说。欢迎大家一起学习交流。

下一篇:MySQL学习笔记_中(数据操作语言(DML_insert&update&delete)、数据定义语言(DDL_create&drop&alter))

MySQL学习笔记_上(select查询)相关推荐

  1. MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结

    MySQL学习笔记_关于MySQL的字符类型VARCHAR长度知识总结 一.VARCHAR存储和行长度限制 1.VARCHAR(N)中,N指的是字符的长度,VARCHAR类型最大支持65535,指的是 ...

  2. MySQL学习笔记(三)— 查询篇(DQL语言)

    文章目录 1. 基础查询 2. 条件查询 3. 排序查询 4. 常见函数 5. 分组查询 6. 连接查询 7. 子查询 8. 分页查询 9. 联合查询 查询所用到的数据库创建脚本myemployees ...

  3. 【数据库和SQL学习笔记】6.SELECT查询4:嵌套查询、对查询结果进行操作

    数据库系统软件:SQL Server 2019 Express 操作系统:Windows 10 文章目录 嵌套查询 IN 与 NOT IN EXISTS 与 NOT EXISTS 比较运算符 SOME ...

  4. mysql 学习笔记第二天 排序查询(超级好懂分享给大家)

    表格中字段 排序查询 # 排序查询 /* 语法:SELECT 查询列表from 表名where 筛选条件order by 排序列表 [asc正序||desc倒叙] */# 案例1:查询员工信息,要求工 ...

  5. MySQL学习笔记7:基本查询

    参考表:student 多字段查询 mysql> select id,name,birth from student; 所有字段查询 mysql> select * from studen ...

  6. MySQL 学习笔记(四)——查询练习

    查询练习 1.准备数据 准备创建 几个表: 学生表(Student):学号.姓名.性别.出生年月日.班级 课程表(Course):课程号.课程名称.教师编号 成绩表(Score) :学号.课程号.成绩 ...

  7. 查询关键字MySQL学习笔记16:子查询 查询关键字

    本篇文章笔者在广东游玩的时候突然想到的...之前就有想写几篇关于查询关键字的博客,所以回家到之后就奋笔疾书的写出来发布了 子查询是将一个查询语句嵌套在另一个查询语句中 内层查询语句的查询结果,可认为外 ...

  8. mysql学习笔记14 多表查询初步

    对数据分组的总结 举例:统计各个部门的平均工资,并且是大于1000的,并且按照平均工资从高到底排序 mysql> select avg(stsal) as myavgsal, stdepno f ...

  9. MySQL 学习笔记②

    若文章内容或图片失效,请留言反馈.部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/BV1Kr4y1i7ru 资料链接 ...

最新文章

  1. 运维工程师的职责和前景
  2. CentOS 安装与优化
  3. matlab入门之旅,MATLAB 入门之旅学习笔记
  4. 通过jQuery源码学习javascript(三)
  5. 18awg线材最大电流_小米生态链拉车线:2.4A大电流,苹果MFi认证,高速充电不断裂...
  6. 不是明年年初?苹果明年三季度才会推出AirPods Pro 2
  7. Android 使用低功耗蓝牙简单介绍
  8. 人口logistic模型公式_人口指数增长模型和Logistic模型
  9. 网站地图(sitemap)在线生成
  10. ab并发测试post请求传参
  11. 第三方平台可以通过微信公众平台素材管理接口实现同步了
  12. 条件运算符 JAVA
  13. xp如何在电脑上设置无线网络连接服务器,xp电脑怎么设置wifi
  14. 【zz】陈硕:当析构函数遇到多线程──C++ 中线程安全的对象回调
  15. R语言对数线性模型loglm函数_用R语言进行数据分析:常规和广义线性模型
  16. 立足小餐饮,“新名酒”江小白能走多远?
  17. 使用Python二次开发S3D 查询当前选择元素基本信息
  18. CSS多行文本溢出隐藏,显示省略号
  19. 英语练习122 Time flies
  20. OpenCV实战(7)——OpenCV色彩空间转换

热门文章

  1. linux桌面稳定吗,【Linux作为桌面系统不稳定的原因?】-看准网
  2. html中内联元素是什么意思,HTML中内联元素指的是什么
  3. Qt程序字体初始化引起的白屏问题
  4. 又双叒叕升级了,Nine 2.0.3正式上线!
  5. Ansible 系列之 Galaxy 工具
  6. 函授大专计算机应用和电子商务选哪个,函授大专该如何选择专业
  7. 祝本站管理员孤星新婚快乐
  8. Spring中redirect和forward的区别
  9. java面试题-京北方、泰康人寿
  10. Ubuntu14.04 科学计算包blas、lapack的安装及其使用