第03章基本的SELECT语句
- SQL的分类
- Select
-- 单行注释
# 单行注释
/*
多行注释
*/
/*
4.导入现有的数据表、表的数据。
方式1: source文件的全路径名
source E:\MySQL\atguigudb.sql;
方式2: 基于具体的图形化界面的工具可以导入数据
比如: SQLyog中选择“工具” --"执行sql脚本”--选中xxx.sql即可。
*/
USE DATABASE atguigudb;
SELECT * FROM employees;
SELECT employee_id,last_name,salary FROM employees;
# 6. 列的别名
# as:全称:alias(别名)
SELECT employee_id,last_name,department_id
FROM employees;
SELECT employee_id emp_id,last_name AS lname,department_id "dep_id",salary * 12 "annual sal"
FROM employees;
# 7.去除重复行
# 查询员工表中一共有哪些部门id呢?
# 错误的:没有去重的情况
SELECT department_id
FROM employees;
# 正确的:去重的情况
SELECT DISTINCT department_id
FROM employees;
#错误的:
SELECT salary,DISTINCT department_id FROM employees;
#仅仅是没有报错,但是没有实际意义。
SELECT DISTINCT department_id,salary FROM employees;
#8.空值参与运算#1.空值:null
#2. null不等同于0,'','null'
SELECT *FROM employees;
#3.空值参与运算:结果一定也为空。
SELECT employee_id,salary "月工资",salary * (1+commission_pct) * 12 "年工资",commission_pct
FROM employees;
# 实际问题的解决方案:引入了ifnull.
SELECT employee_id,salary "月工资",salary * (1+IFNULL(commission_pct,0)) * 12 "年工资",commission_pct
FROM employees;
#9. 着重号 ` `
#和关键字冲突,要用着重号
SELECT *FROM `ORDER`;
#10 查询常数
SELECT '马志斌',123,employee_id,last_name
FROM employees;
#11 显示表结构
DESCRIBE employees;
DESC departments;
#12.过滤数据
#练习:查询90号部门的员工信息
SELECT *
FROM employees
#过滤条件
WHERE department_id = 90;
#练习:查询last_name为King的员工信息
SELECT *
FROM employees
#过滤条件
WHERE last_name = 'King';
运算符
#运算符 “=”
#字符串存在隐式转换。如果转换数值不成功,则看做0
#两边都是字符串的话,则按照ANSI的比较规则进行比较。
#只要有null参与判断,结果就为null
#运算符 “<=>”
# 为null而生,结果不会有null
#2.2
#IS NULL \IS NOT NULL \ISNULL
#练习:查询表中commission pct为null的数据有哪些
SELECT last_name,salary,commission_pct
FROM employees
WHERE commission_pct IS NULL;
#或
SELECT last_name,salary,commission_pct
FROM employees
WHERE ISNULL(commission_pct);
#练习:查询表中commission pct不为null的数据有哪些
SELECT last_name,salary,commission_pct
FROM employees
WHERE commission_pct IS NOT NULL;
#或
SELECT last_name,salary,commission_pct
FROM employees
WHERE NOT commission_pct <=> NULL;
#2.3 最小的LEAST,最大的GREATEST
SELECT LEAST('a','k','v'),GREATEST(99,7,50)
FROM DUAL;
#2.4 BETWEEN条件下界1 AND条件上界2(查询条件1和条件2范围内的数据,包含边界)
#查询工资在6000到8000的员工信息
SELECT employee_id,last_name,salary
FROM employees
-- WHERE salary BETWEEN 6000 and 8000;
WHERE salary >=6000 && salary <= 8000;
#查询工资不在6000到8000的员工信息
SELECT employee_id,last_name,salary
FROM employees
WHERE salary < 6000 OR salary > 8000;
#2.5 in (set) \ not in (set)
#练习:查询部门为10,20,30部门的员工信息
SELECT employee_id,salary,department_id
FROM employees
-- WHERE department_id = 10 or department_id = 20 or department_id = 30;
WHERE department_id in(10,20,30);
#练习:查询工资不是6000,7000,8000的员工信息
SELECT employee_id,salary,department_id
FROM employees
-- WHERE department_id = 10 or department_id = 20 or department_id = 30;
WHERE salary NOT in(6000,7000,8000);
#2.6 LIKE ∶模糊查询
#练习:查询last_name中包含字符'a'的员工信息
# %:代表不确定个数的字符。
SELECT employee_id,last_name,salary,department_id
FROM employees
WHERE last_name LIKE '%a%';
#练习:查询last _name中以字符'a'开头的员工信息
SELECT employee_id,last_name,salary,department_id
FROM employees
WHERE last_name LIKE 'a%';
#练习:查询last name中包含字符'a'且包含字符'e'的员工信息
#写法1:
SELECT employee_id,last_name,salary,department_id
FROM employees
WHERE last_name LIKE '%a%' AND last_name LIKE '%e%';
#写法2:
SELECT employee_id,last_name,salary,department_id
FROM employees
WHERE last_name LIKE '%a%e%' OR last_name LIKE '%e%a%';
# _:代表一个不确定的字符
#查询第2个字符是'a'的员工信息
SELECT employee_id,last_name,salary,department_id
FROM employees
WHERE last_name LIKE '__a%';
#练习:查询第2个字符是_且第3个字符是'a '的员工信息
#需要使用转义字符:\
SELECT employee_id,last_name,salary,department_id
FROM employees
WHERE last_name LIKE '_\_a%';
#2.7 REGEXP\RLIKE :正则表达式
# 是不是以m开头,是不是以n结尾,是不是包含hi。
SELECT 'mahibin' REGEXP '^m','mahibin' REGEXP 'n$','mahibin' REGEXP 'hi'
FROM DUAL;
#XOR:追求的"异"
-- 练习:id等于50的,salary都小于6000,salary大于6000的,id都不等于50
SELECT last_name, salary , department_id
FROM employees
WHERE department_id = 50 XOR salary > 6000;
#注意:AND的优先级高于oR
#4.位运算符:& | ^ ~ >> <<
# &:有零则零,全一则一
# |:有一则一,全零则零
# ^:相同为零,相异为一
# ~:按位取反
SELECT 12 & 5,12|5,12^5
FROM DUAL;
SELECT 10 & ~1
FROM DUAL;
#在一定范围内满足:每向左移动1位,相当于来以2;每间石移动一位,相当于陈以2。
SELECT 4 << 1, 8 >>1
FROM DUAL;
排序与分页
#1.排序
#如果没有使用排序操作,默认情况下查询返回的数据是按照添加数据的顺序显示的。
SELECT *FROM employees;
#使用 ORDER_BY对查询到的数据进行排序操作。
#升序:ASC(ascend)
#降序:DESC(descend)
#练习:按照salary从高到低的顺序显示员工信息
SELECT employee_id,last_name,salary
from employees
order BY salary DESC;
#练习:按照salary从低到高的顺序显示员工信息
#如果在ORDER BY后没有显式指名排序的方式的话,则默认按照升序排列。
SELECT employee_id,last_name,salary
from employees
order BY salary ASC;
#我们可以使用列的别名,进行排序
SELECT employee_id,salary,salary*12 annual_sal
FROM employees
ORDER BY annual_sal;
#列的别名只能在ORDER BY 中使用,不能在where中使用
SELECT employee_id,salary,salary*12 annual_sal
FROM employees
WHERE annual_sal > 80000;
#强调格式:WHERE 需要声明在FROM后,ORDER BY之前。
SELECT employee_id,salary,department_id
FROM employees
WHERE department_id in(50,60,70)
ORDER BY department_id DESC;
#二级排序
#练习:显示员工信息,按照department_id的降序排列,salary的升序排列
SELECT employee_id,salary,department_id
FROM employees
order by department_id DESC,salary ASC;
#分页
#mysql使用limit实现数据的分页显示
#需求一:每页显示20条记录,此时显示第1页
SELECT employee_id,salary
FROM employees
LIMIT 0,20;
#需求二:每页显示20条记录,此时显示第2页
SELECT employee_id,salary
FROM employees
LIMIT 20,20;
#需求三:每页显示20条记录,此时显示第2页
SELECT employee_id,salary
FROM employees
LIMIT 40,20;
#需求:每页显示pagesize条记录,此时显示第pageNo页:
#公式:LIMIT (pageNo-1)* pagesize,pagesize;
#2.2 WHERE ... ORDER BY ...LIMIT 声明顺序如下:
#LIMIT的格式:严格来说:LIMIT位置偏移量,条目数
#结构"LIMIT 0,条目数”等价于"LIMIT条目数"
SELECT employee_id,last_name,salary
FROM employees
WHERE salary > 6000
ORDER BY salary DESC
-- LIMIT 0,10;
LIMIT 10;
#练习:表里有107条数据,我们只想要显示第 32、33条数据怎么办呢?
SELECT *
FROM employees
LIMIT 31,2;
#mysql8.0 新特性:limit... OFFSET...
#练习:表里有107条数据,我们只想要显示第 32、33条数据怎么办呢?
SELECT *
FROM employees
LIMIT 2 OFFSET 31;
#练习:查询员工表中工资最高的员工信息
SELECT employee_id,last_name,salary
FROM employees
ORDER BY salary DESC
LIMIT 1;
多表查询
#多表查询
DESC employees;
DESC departments;
DESC locations;
#查询员工名为' Abel'的人在哪个城市工作?
SELECT *
FROM employees
WHERE last_name = 'Abel';
SELECT *
FROM departments
WHERE department_id = 80;
SELECT *
FROM locations
WHERE location_id = 2500;
#出现笛卡尔积的错误
#错误的原因:缺少了多表的连接条件
#错误的实现方式:每个员工都与每个部门匹配了一遍。
SELECT employee_id,department_name
FROM employees,departments;#查询出2889条记录
#错误的方式:CROSS JOIN
SELECT employee_id, department_name
FROM employees CROSS JOIN departments;#查询出2889条记录
#3. 多表查询的正确方式
SELECT employee_id, department_name
FROM employees,departments
#两个表的连接条件
WHERE employees.department_id = departments.department_id;
#4.如果查询语句中出现了多个表中都存在的字段,则必须指明此字段所在的表。
SELECT employees.employee_id, departments.department_name,employees.department_id
FROM employees,departments
WHERE employees.department_id = departments.department_id;
#建议:从sql优化的角度,建议多表查询时,每个字段前都指明其所在的表。
#5.可以给表起别名,在SELECT和wHERE中使用表的别名。
#如果给表起了别名,一旦在SELECT或wHERE中使用表名的话,则必须使用表的别名,而不能再使用表的原名。
SELECT emp.employee_id, dept.department_name,emp.department_id
FROM employees emp,departments dept
WHERE emp.department_id = dept.department_id;
#6. 如果有n个表实现多表的查询,则需要至少n-1个连接条件
#练习:查询员工的employee_id,last_name , department_name,city
SELECT e.employee_id,e.last_name , d.department_name,l.city,e.department_id,l.location_id
FROM employees e,departments d,locations l
WHERE e.department_id = d.department_id
AND d.location_id = l.location_id;
#7.多表查询的分类/*
/*
角度1:等值连接 vs 非等值连接
角度2:白连接 vs 非自连接
角度3:内连接 vs 外连接
*/
#7.1 等值连接 vs 非等值连接
#非等值连接的例子:
SELECT *
FROM job_grades;
SELECT e.last_name,e.salary,j.grade_level
FROM employees e,job_grades j
-- WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
WHERE e.salary >= j.lowest_sal AND e.salary <= j.highest_sal;
#7.2 自连接 vs 非自连接
SELECT * FROM employees;
#练习:查询员工id,员工姓名及其管理者的id和姓名
SELECT emp.employee_id,emp.last_name,mgr.employee_id,mgr.last_name
FROM employees emp,employees mgr
WHERE emp.manager_id = mgr.employee_id;
#7.3 内连接 vs 外连接
#内连接:合并具有同一列的两个以上的表的行,结果集中不包含一个表与另一个表不匹配的行
SELECT employee_id, department_name
FROM employees e,departments d
WHERE e.department_id = d.department_id; #只有106条记录
#外连接:合并具有同一列的两个以上的表的行,结果集中除了包含一个表与另一个表匹配的行之外,
# 还查询到了左表或右表中不匹配的行。
#外连接的分类:左外连接、右外连接、满外连接
#左外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左表中不满足条件的行,这种连接称为左外连接
#右外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回右表中不满足条件的行,这种连接称为右外连接
#练习:查询所有的员工的last_name , department_name信息
SELECT employee_id, department_name
FROM employees e,departments d
WHERE e.department_id = d.department_id; #需要使用左外连接
#SOL92语法实现内连接:见上,略
#SQL92语法实现外连接:使用+ 但是MySQL不支持SQL92语法外连接的写法!Orcal可以
SELECT employee_id, department_name
FROM employees e,departments d
WHERE e.department_id = d.department_id(+);
#SQL99语法中使用JoIN ...ON的方式实现多表的查询。这种方式也能解决外连接的问题。MysQL是支持此种方式的
#SQL99语法实现内连接:两张表
SELECT last_name,department_name
FROM employees e INNER JOIN departments d #INNER可以省略
ON e.department_id = d.department_id;
#三张表
SELECT last_name,department_name,city
FROM employees e JOIN departments d
ON e.department_id = d.department_id
JOIN locations l
ON d.location_id = l.location_id;
#SQL99语法实现外连接:
#练习:查询所有的员工的last _name , department_name信息
#左外连接
SELECT last_name,department_name
FROM employees e LEFT OUTER JOIN departments d
ON e.department_id = d.department_id;
#右外连接
SELECT last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id;
#满/全外连接
SELECT last_name,department_name
FROM employees e FULL OUTER JOIN departments d
ON e.department_id = d.department_id;
#8.UNION 和 UNIONALL的使用
#UNION: 会执行去重操作
#UNION ALL:不会执行去重操作
#结论:如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,
#则尽量使用UNION ALL语句,以提高数据查询的效率。
# 9. 7种JOIN的实现:
# 中图:内连接(106条记录)
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.department_id = d.department_id;
#左上图:左外连接(107条记录)
SELECT employee_id,last_name,department_name
FROM employees e LEFT OUTER JOIN departments d
ON e.department_id = d.department_id;
#右上图:右外连接(122条记录)
SELECT employee_id,last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id;
#左中图:(1条记录)
SELECT employee_id,last_name,department_name
FROM employees e LEFT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE d.department_id is NULL;
#右中图:(16条记录)
SELECT employee_id,last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE e.department_id is NULL;
#左下图:满外连接(123条记录)
#方式一:左上图 UNION ALL 右中图
SELECT employee_id,last_name,department_name
FROM employees e LEFT OUTER JOIN departments d
ON e.department_id = d.department_id
UNION ALL
SELECT employee_id,last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE e.department_id is NULL;
#方式二:右上图 UNION ALL 左中图
SELECT employee_id,last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id
UNION ALL
SELECT employee_id,last_name,department_name
FROM employees e LEFT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE d.department_id is NULL;
#右下图:左中图 UNION ALL 右中图(17条记录)
SELECT employee_id,last_name,department_name
FROM employees e LEFT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE d.department_id is NULL
UNION ALL
SELECT employee_id,last_name,department_name
FROM employees e RIGHT OUTER JOIN departments d
ON e.department_id = d.department_id
WHERE e.department_id is NULL;
单行函数