语法:USE 数据库名;
用于启动需要的数据库
语法:SHOW TABLES;
用于查看当前数据库中的所有的表
语法:DESC 表名;
用于查看表的结构
(+) 其功能只有一个:做数值型的加法运算
例如:SELECT 1 + 2; – 3
注意:
⑴ 不能将列名用+号连接。如果要拼接列的值,应当使用CONCAT函数【见下面6、函数中的CONCAT】
⑵ 如果纯字符串和数值字符串相加,则结果为数值字符串的值。如:SELECT 1 + ‘a’; – 1
⑶ 如果纯字符串和纯字符串相加,则结果为0。如: SELECT ‘a’ + ‘b’; – 0
⑷ 任何值和null相加结果都为null
> 大于
< 小于
= 等于
>= 大于等于
<= 小于等于
<> 不等于
例如:
⑴ 查询employees表中,salary大于2000的员工信息
SELECT * FROM employees
WHERE salary > 2000;
⑵ 查询employees表中,salary不等于6000的员工信息
SELECT * FROM employees
WHERE salary <> 6000;
AND 和
OR 或
NOT 非
语法:NOT(条件)
例如:
⑴ 查询employees表中,salary在6000和8000之间的员工信息
SELECT * FROM employees
WHERE salary >= 6000 AND salary <= 8000;
⑵ 查询employees表中,salary是5000或9000的员工信息
SELECT * FROM employees
WHERE salary = 5000 OR salary = 9000;
⑶ 查询employees表中,salary在5000以下的员工信息(salary 不是 >= 5000)
SELECT * FROM employees
WHERE NOT(salary >= 5000);
如果列中的值包含下划线或百分号,则需要使用转义字符。可以使用任意字符充当转义字符,但是需要声明,使用ESCAPE关键字。
示例:
⑴ 查询employees表中last_name第二个字符为%的员工信息
SELECT * FROM employees
WHERE last_name LIKE ‘_ ’;
⑵ 查询employees表中,last_name包含ase的员工信息
SELECT * FROM employees
WHERE last_name LIKE ‘%ase%’;
⑶ 查询employees表中,last_name的第三个字符为a的员工信息
SELECT * FROM employees
WHERE last_name LIKE ‘__a%’;
⑷ 查询employees表中,last_name的第二个字符为_(下划线),最后一个字符为a的员工信息
SELECT * FROM employees
WHERE last_name LIKE ‘$%a’ ESCAPE ‘$’;
BETWEEN AND 在某个范围内
语法:BETWEEN 值1 AND 值2
注意:值1不能大于值2
即等同于:? >= 值1 AND ? <= 值2
BETWEEN AND的效率要高于关系运算符
示例:
查询employees表中,salary在6000和9000范围内的员工信息
SELECT * FROM employees
WHERE salary BETWEEN 6000 AND 9000;
IN 属于列值中的一个
语法:列名 IN(值1, 值2, …);
即等同于:列名 = 值1 OR 列名 = 值2 OR 列名 = …
IN 的效率要高于关系运算符
示例:
查询employees表中,salary为6000或7000或8000的员工信息
SELECT * FROM employees
WHERE salary IN(6000, 7000, 8000);
IS NOT NULL 是否不为空
IS NULL 是否为空
示例:
⑴ 查询employees表中,没有bonus(bonus为null的)的员工信息
SELECT * FROM employees
WHERE bonus IS NULL;
⑵ 查询employees表中,含有bonus的员工信息
SELECT * FROM employees
WHERE bonus IS NOT NULL;
去除重复的值
示例:
查询employees表中,所有的department_id
SELECT DISTINCT department_id
FROM employees;
SELECT * | 列名 FROM 表名
【WHERER 条件】
ORDER BY 排序的字段 【ASC | DESC】
ASC 升序 【默认是升序,可以省略】
DESC 降序 【不可省略】
可以按照多个字段进行排序,之间用逗号(,)隔开
语句的执行顺序:
⑴ 首先查看表是否存在,如果不存在则报错:
ERROR 1146 (42S02): Table ‘表名’ doesn’t exist
⑵ 其次查看要查询什么列,即SELECT后面的语句
⑶ 再查看要查询什么行,即WHERE后面的语句
⑷ 最后看是升序还是降序。再显示出来
特点:
⑴ 可以按单个字段排序
⑵ 也可以按多个字段排序
⑶ 可以按表达式排序
⑷ 可以按别名排序
⑸ 可以按函数的返回值排序
函数,判断某个字段或值是否为空,返回值为1【true】或0【false】
语法:ISNULL();
示例:
判断employees表中employee_id为104的员工的bonus是否为空
SELECT ISNULL(bonus) FROM employees
WHERE employee_id = 104;
语法:IFNULL(expr1, expr2)
函数,判断某个字段或值是否为空。要传入两个参数:expr1为要判断的值;expr2为当expr1为空时,作为返回值返回。即如果expr1不为空则返回expr1,如果为空则返回expr2。
示例:
求出employees表中所有员工的年薪
【年薪 = 月工资 * (1 + 奖金率)】
SELECT last_name, (salary * (1 + IFNULL(commission_pct, 0))) AS ‘年薪’
FROM employees;
⑴ 查询employees表中所有员工的last_name, salary,并按照salary降序
SELECT last_name, salary
FROM employees
ORDER BY salary DESC;
⑵ 查询employees表中所有员工的last_name,salary,并先按照last_name升序,再按照salary降序
SELECT last_name, salary
FROM employees
ORDER BY last_name, salary DESC;
传入一个数值,最终得到一个结果
示例:SELECT LOWER(‘Hello MySQL!’); – hello mysql!
示例:SELECT UPPER(‘Hello MySQL!’); – HELLO MYSQL!
语法:CONCAT(str1, str2, …)
连接多个字符,参数之间用逗号隔开
示例:查询employees表中所有员工的姓名
SELECT CONCAT(last_name, ’ ‘, first_name) AS ‘姓名’
FROM employees
⑴ 语法:SUBSTR(str, pos)
截取字符,从索引位置处一直到最后都截取出来
注意:索引从1开始
示例:
SELECT SUBSTR(‘Hello MySQL!’, 7); – MySQL!
⑵ 语法:SUBSTR(str, pos, len)
截取字符,从索引位置处,截取指定长度
注意:索引从1开始
示例:
SELECT SUBSTR(‘Hello MySQL!’, 9, 3); – SQL
语法:LENGTH(str)
获取字节长度
注意:获取到的字符长度和当前数据库的字符编码有关【主要是汉字的字节长度不一定】
示例:
SELECT LENGTH(‘你好 MySQL!’); – 6 + 1 + 6 = 13
解释:当前数据库的字符编码为utf8,一个汉字占3个字节,两个汉字共6个字节;1个空格,5个字母,1个感叹号。所以最终为13个字节。
注意:汉字输入的符号所占字节数和汉字所占字节数一致。
示例:
SELECT LPAD(‘abc’, 8, ‘%’); – %%%%%abc
解释:字符串abc的长度为3个字符,第二个设置填充后的字符串长度为8,所以用指定填充字符串%,左填充5(8 - 3)位。
SELECT LPAD(‘abc’, 5, ‘好’); – 好好abc
解释:填充2个字符(5 - 3【abc的长度】),不是按字符的字节数
SELECT LPAD(‘abc’, 2, ‘好’); – ab
解释:第二个参数小于abc的长度,所以截取abc的前两位,即ab
RPAD(str, len, padstr)
用指定的填充字符串,右填充到指定字符串。填充数量为(第二个参数 - 指定字符串长度)。第一个参数为要填充的字符串,第二个参数为填充后的字符串长度。第三个参数为指定的填充字符串。
注意:若第二个参数小于要填充的字符串,则从左开始截取第二个参数的字符。相当于SUBSTR(要填充的字符串, 第二个参数)
示例:
SELECT RPAD(‘abcd’, 6,’好’); – abcd好好
SELECT RPAD(‘abcd’, 2,’好’); – ab
解释:第二个参数小于abcd的长度,所以截取abcd的前两位,即ab
示例:
SELECT TRIM(’ ’ FROM ’ [ab c de] ‘); – [ab c de]
⑵ TRIM(LEADING remstr FROM str)
将remstr中左端的str去除。注意LEADING关键字和FROM关键字不可改变
示例:
SELECT TRIM(LEADING ‘a’ FROM ‘aaHello MySQLaaa’); – Hello MySQLaaa
⑶ TRIM(TRAILING remstr FROM str)
将remstr中左端的str去除。注意TRAILING关键字和FROM关键字不可改变
示例:
SELECT TRIM(TRAILING ‘a’ FROM ‘aaHello MySQLaaa’); – aaHello MySQL
REPLACE(str, from_str, to_str)
替换
示例:
SELECT REPLACE(‘He110’, ‘110’, ‘LLO’); – HeLLO
处理数值型的数据
⑴ ROUND(X)
四舍五入,舍掉小数点后面的数
示例:
SELECT ROUND(34.534); – 35
⑵ ROUND(X, D)
四舍五入,舍掉小数点后的指定位数后面的数
示例:
SELECT ROUND(34.534, 2); – 34.53
示例:
SELECT TRUNCATE(23.3494, 2); – 23.34
MOD(n, m)
取余
示例:
SELECT MOD(10, -3); – (1)
SELECT MOD(-5, 2); – (-1)
示例: SELECT NOW(); – (yyyy-MM-dd hh:mm:ss)
CURDATE()
获取日期
示例: SELECT CURDATE(); – (yyyy-MM-dd)
用于做统计的,传入一组值,最终得到一个值
MAX(expr)
求最大值
MIN(expr)
求最小值
⑴ 和分组函数一同查询的列必须是分组后的列(因为它们是一一对应的关系)
⑵ 分组函数的参数一般是列名,只有COUNT()的参数可以为* ,即COUNT(*)
⑶ 所有的分组函数,都忽略NULL值
语法:
CASE 要判断的字段或表达式
WHEN 条件1 THEN 值1
WHEN 条件2 THEN 值2
WHEN 条件3 THEN 值3
ELSE 默认值
END
注意:WHEN后只能写常量值,不能是BETWEEN…AND之类的判断。
示例:查询employees表中department_id为10,20,30的员工信息,若部门号为10,则打印其工资的1.1倍,20号部门,则打印其工资的1.2倍,30号部门打印其工资的1.3倍数。其他为默认值。
SELECT department_id,
CASE department_id
WHEN 10 THEN salary * 1.1
WHEN 20 THEN salary * 1.2
WHEN 30 THEN salary * 1.3
ELSE salary
END ‘new salary’
FROM employees;
SELECT 分组函数 | 被分组的列
FROM 表
【WHERE 分组前的条件】
GROUP BY 被分组的列
【HAVING 分组后的条件】
示例:查询employees表中,每个department的最大salary
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id;
分组前的条件:使用WHERE 条件
注意:再次强调:WHERE 的条件不可以使用列的别名
特点:分组前的条件一般可以在原始表(没有分组前的表)中找到
示例:查询employees表中,每个department中last_name包含e的员工的最大salary,department_id,last_name
SELECT MAX(salary), department_id, last_name
FROM employees
WHERE last_name LIKE ‘%e%’
GROUP BY department_id;
分组后的条件:使用HAVING 条件
特点:⑴ 条件是根据分组后的结果集进行筛选,一般判断的列就是分组函数或分组的列
⑵ 多个分组条件没有先后顺序之说
⑶ 执行顺序:WHERE – GROUP BY – HAVING
⑷ SELECT 列 FROM 表 HAVING 分组前条件
这条语句也正确,但是效率比WHERE低
⑸ HAVING支持别名做筛选
示例:查询最低salary大于5000的部门的最低工资和department_id
分析:
⑴ 首先要找出各个部门的最低工资,数据不止一个,所以要使用GROUP BY进行分组
⑵ 根据分组后的结果,查找最低工资大于5000的部门,所以是分组后加筛选条件,所以使用HAVING
步骤:
⑴ 查询各个部门的最低工资
SELECT MIN(salary), department_id
FROM employees
GROUP BY department_id;
⑵ 查询最低工资大于5000的部门
SELECT MIN(salary), department_id
FROM employees
GROUP BY department_id
HAVING MIN(salary) > 5000;
⑴ 和分组函数一起查询的可以是被分组的列
⑵ 解题步骤:
① 先分组
② 找筛选条件:如果条件所判断的是分组函数,则绝对要放在HAVING的后面;如果数据来自原始表,则放在WHERE的后面
SELECT 列名1, 列名2
FROM 表1, 表2
WHERE 连接条件
现象:最终的结果 = 表1的行数 × 表2的行数
出现的原因:没有加连接条件。
即 SELECT 列名1, 列名2
FROM 表1, 表2
需要添加连接条件来解决
⑴ 等值连接 – 非等值连接
⑵ 内连接 – 外连接
⑶ 自连接
错误代码:1052
Column ‘???’ in field list is ambiguous
这种错误是由于指定的列不明确造成的。一般是由于查询的列,在查询的多个表中都有,即多个表含有相同的字段。
解决的方法是:使用【表名.列名】将其限制。
特点:
⑴ 表1和表2的顺序可以调换
⑵ 两表连接需要1个条件,n表连接需要n-1个条件
⑴ 【普通的两表等值连接】
示例:查询first_name和department_name
分析:需要查找姓名和部门名,而这两个字段来自两个表,所以要将两个表连接起来,并加连接条件:两个表的字段值要相等
SELECT first_name, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id;
Tips:可以个表起个别名,方便调用表中的字段
⑵ 【添加筛选条件】
示例:查询有commission_pct的last_name和department_name
分析:
① 要查找员工名和部门名,需要将employees和departments连接起来
② 没有奖金,就是继续追加分组前的筛选条件
SELECT last_name, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id
AND commission_pct IS NOT NULL
⑶ 【添加分组】
示例:查询每个job_id的job_title和平均salary
分析:
① 查找工种名需要将jobs表和employees表连接起来,连接条件为job_id相等
② 其次还要查找平均工资,结果不止一个,所以要用GROUP BY进行分组
SELECT job_title, AVG(salary)
FROM employees e, jobs j
WHERE e.job_id = j.job_id
GROUP BY job_title;
示例:查询员工的工资级别
分析:
employees表中有salary,而salary_grades表中有grade、max_salary和min_salary三个字段。所以要使用BETWEEN…AND将这两个连接起来
SELECT grade, salary
FROM employees, salary_grades
WHERE salary BETWEEN min_salary AND max_salary;
语法:关键词:JOIN ON
SQL99语法(SQL1999)
分类:
内连接:表1 [INNER] JOIN 表2 ON 连接条件
INNER 可以省略
外连接:
表1 LEFT [OUTER] JOIN 表2 ON 连接条件
OUTER 可以省略
左外连接
表1 RIGHT [OUTER] JOIN 表2 ON 连接条件
OUTER 可以省略
右外连接
FULL OUTER JOIN ON
全外连接(MySQL不支持)
SELECT first_name, department_name
FROM employees e INNER JOIN departments d
ON e.department_id = d.department_id;
⑵ 示例:【添加筛选条件】
查询有commission_pct的last_name和department_name
SELECT last_name, department_name
FROM employees e INNER JOIN departments d
ON e.department_id = d.department_id
WHERE commission_pct IS NOT NULL;
⑶ 示例:【添加分组】
查询每个job_id的job_title和平均salary
SELECT job_title, AVG(salary)
FROM jobs j INNER JOIN employees e
ON j.job_id = e.job_id
GROUP BY job_title;
即 主表某列的记录: 1 2 3 4
从表某列的记录: 1 2
注:某列为主从表相同的字段
结果集:
主表 从表
1 1
2 2
3 NULL
4 NULL
③ 一般用于查询主表中有,而从表中没有的数据
④ 左外连接和右外连接互换主从表的顺序,并更换LEFT | RIGHT 关键字,可以达到相同的效果
Tips:在解题前先想清楚,哪个表的字段要全部显示【主表】,哪个表的字段中含有NULL值【从表】。
【一般是】
SELECT 主表字段, 从表.主从相同字段
FROM 主表 LEFT OUTER JOIN 从表
ON 主表.主从相同字段 = 从表.主从相同字段
WHERE 从表.主从相同字段 IS NULL | 从表.主从相同字段 IS NOT NULL;
⑴ 示例:显示哪个部门中没有员工
分析:
显示没有员工的部门,即departments表中的department_id的数量要比employees表中的department_id的数量多。所以departments表当主表,而employees表当从表。
① 首先显示出主表中所有的department_name
SELECT e.department_id, department_name
FROM departments d LEFT OUTER JOIN employees e
ON d.department_id = e.department_id;
② 从输出的结果可以看出:e.department_id列含有NULL值,所以接下来应当判断:e.department_id有NULL值,即为没有员工的部门
SELECT e.department_id, department_name
FROM departments d LEFT OUTER JOIN employees e
ON d.department_id = e.department_id
WHERE e.department_id IS NULL;
⑵ 示例:查询哪个国家没有部门
分析:
查询哪个国家没有部门,即locations表的location_id的数量比departments表的location_id数量多。所以locations表当主表,departments当从表
SELECT country_id, d.location_id
FROM locations l LEFT OUTER JOIN departments d
ON l.location_id = d.location_id
WHERE d.location_id IS NULL;
注意:在解题前先想清楚,哪个表的字段要全部显示【主表】,哪个表的字段中含有NULL值【从表】。
【一般是】
SELECT 主表字段, 从表.主从相同字段
FROM 从表 RIGHT OUTER JOIN 主表
ON 主表.主从相同字段 = 从表.主从相同字段
WHERE 从表.主从相同字段 IS NULL | 从表.主从相同字段 IS NOT NULL;
示例:显示哪个部门中没有员工
分析:将左连接中主表从表的顺序调换,再将LEFT替换为RIGHT即可
SELECT e.department_id, d.department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE e.department_id IS NULL;
执行主查询时又用到了子查询的结果
主查询:外查询
子查询:内查询
执行顺序:子查询优先于主查询执行
注意:
⑴ 一般会将子查询放到小括号中
⑵ 子查询一般放在右侧
分类:
⑴ 单行子查询:
子查询的结果是一个值
搭配单行操作符:>, <, =, <>, >=, <=
⑵ 多行子查询:
子查询的结果是一组值
需要搭配多行操作符:ANY/ALL/IN
ANY:和子查询结果中的某一个值比较
一般搭配 > 或 < 来使用即
> ANY (子查询) 或 < ANY (子查询)
ALL:和子查询结果中所有的值比较
一般搭配 > 或 < 来使用即
> ALL (子查询) 或 < ALL (子查询)
IN:等于子查询结果中的任意一个值
IN (子查询)
类似于:IN(值1, 值2, 值3, …)
① 首先查找’Bone’的工资
SELECT salary
FROM employees
WHERE last_name = ‘Bone’;
② 其次查找谁的工资比①的结果要高
SELECT last_name
FROM employees
WHERE salary > (
SELECT salary
FROM employees
WHERE last_name = ‘Bone’
);
⑵ 示例:【子查询用到了分组函数】
返回公司工资最少的员工的last_name,job_id和salary
① 查找公司的最低工资是多少
SELECT MIN(salary)
FROM employees;
② 查找哪位员工的工资为①中的结果
SELECT last_name, job_id, salary
FROM employees
WHERE salary = (
SELECT MIN(salary)
FROM employees;
);
⑶ 示例:【子查询用到了HAVING】
查询最低salary大于50号部门的最低工资的部门编号和最低工资
① 查询50号部门的最低工资
SELECT MIN(salary)
FROM employees
WHERE department_id = 50;
② 查询每个部门的最低工资
SELECT department_id, MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) > (
SELECT MIN(salary)
FROM employees
WHERE department_id = 50
);
⑴ 示例:【返回其他部门中比job_id为’IT_PROG’部门任意一个工资低的员工的员工号、姓名、job_id 以及salary】
① 查询job_id为’IT_PROG’部门的所有工资情况
SELECT salary
FROM employees
WHERE job_id = ‘IT_PROG’;
② 再查找其他部门的工资情况,和①相比,并查找要求的字段
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ANY (
SELECT salary
FROM employees
WHERE job_id = ‘IT_PROG’;
);
⑵ 示例:【返回其它部门中比job_id为’IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id 以及salary】
① 查询job_id为’IT_PROG’部门的所有工资情况
SELECT salary
FROM employees
WHERE job_id = ‘IT_PROG’;
② 再查找其他部门的工资情况,和①相比,并查找要求的字段
SELECT employee_id, last_name, job_id,salary
FROM employees
WHERE salary < ALL (
SELECT salary
FROM employees
WHERE job_id = ‘IT_PROG’;
);