语法:
SELECT 列名 FROM 表名;SELECT last_name FROM employees;SELECT
last_name,
salary,
email #最后一个列名不加","FROM
employees ;SELECT*FROM employees;#顺序与表完全一致SELECT employees.last_name FROM myemployees.employees;#使用完全限定的列名、表名SELECT VERSION();#函数SELECT100%98;#表达式SELECT100;#常量值SELECT"john";
1.1 AS \ DISTINCT \ Concat() \ LIMIT
SELECT last_name AS 姓;#起别名SELECT last_name 姓;#AS可省略SELECT salary AS"out put"FROM employees;SELECTDISTINCT department_id FROM employees;#去重#错误写法: SELECT DISTINCT a,b FROM c; 得到的结果不规则SELECT Concat(last_name,'_',first_name)AS 姓名 FROM employees;SELECT last_name FROM employees LIMIT5;#行0开始,返回不多于5行SELECT last_name FROM employees LIMIT5,5;#行5开始,返回不多于5行
二、条件查询【WHERE…】
2.1 > < = >= <= <> != <=>
条件运算符:><=>=<=<>(不等于)、!=(不等于、新增的)<=>(安全等于,可判断null和普通类型的值)
其中:
<> 或 = 不能用于判断null值,可读性高,建议使用
<=> 既可以判断null,也可判断普通数值,可读性较低
SELECT*FROM employees WHERE salary>12000;SELECT last_name, department_id FROM employees WHERE department_id<>90;SELECT last_name,salary FROM employees WHERE salary <=>12000;#查询工资为12000的员工信息
2.2 AND \ OR \ NOT
逻辑运算符:&&|| !
ANDORNOTSELECT`last_name`,`salary`,`commission_pct`FROM employees WHERE salary>10000&&salary<20000;SELECT*FROM employees WHERE(department_id<90OR`department_id`>110)AND salary >=15000;#AND优先级高,使用AND、OR操作符的WHERE子句都要加括号明确分组
2.3 LIKE \ BETWEEN AND \ IN \ IS NOT NULL
like
可判断字符型或数值型
与通配符搭配:%任意多个字符,包括0个
_任意单个字符
betweenand
提高简洁度,包含临界值,临界值顺序固定
in 或 notin
提高简洁度,判断是否属于IN列表中的某一项,IN列表内值类型兼容,不支持通配符
isnull 或 isnotnull
判断null值
SELECT*FROM employees WHERE last_name LIKE"%a%";#查询员工名包含字符a的员工信息SELECT*FROM employees WHERE last_name LIKE"__n_l%";#查询员工名第三个字符为n,第五个为l的员工信息select*from employees where last_name like “%%”;#不包含nullSELECT*FROM employees WHERE employee_id BETWEEN100AND120;#查询员工编号100~120的员工信息SELECT last_name, job_id FROM employees WHERE job_id IN('IT_PROG','AD_VP','AD_PRES');#查询员工工种编号是 IT_PROG、AD_VP、AD_PRES的员工名和工种编号SELECT last_name,commission_pct FROM employees WHERE commission_pct ISNULL;#查询没有奖金的员工名和奖金率
语法:
SELECT 分组函数,列(要求出现在 GROUPBY 的后面)FROM 表
(WHERE 筛选条件)GROUPBY 分组的字段
(ORDERBY 排序的字段);
特点:
1、和分组函数一同查询的字段必须是groupby后出现的字段
2、筛选分为两类:
针对的表 位置 连接的关键字
分组前筛选 原始表 groupby前 where
分组后筛选 groupby后的结果集 groupby后 having
分组函数做条件肯定放在having子句中
一般来讲,能用分组前筛选的,尽量使用分组前筛选,提高效率
3、分组可以按单个字段也可以按多个字段,逗号隔开,无顺序要求,也支持表达式和函数
4、可以搭配着排序使用,排序放在分组查询最后面
SELECTAVG(salary),job_id
FROM employees
GROUPBY job_id;#查询每个工种的员工平均工资SELECTCOUNT(*),location_id
FROM departments
GROUPBY location_id;#查询每个地区的部门个数
5.1 分组前筛选【WHERE…】
SELECTMAX(salary),department_id
FROM employees
WHERE email LIKE'%a%'#注意where的位置GROUPBY department_id;#查询邮箱中包含a字符的 每个部门的最高工资
5.2 分组后筛选【HAVING…】
SELECTCOUNT(*),department_id
FROM employees
GROUPBY department_id
HAVINGCOUNT(*)>5;#查询哪个部门的员工个数>5
5.3 按表达式或函数分组
SELECTCOUNT(*) count,LENGTH(last_name) len_name #MySQL支持group by和having后加别名FROM employees
GROUPBY len_name
HAVING count>5;#按员工姓名的长度分组,筛选员工个数>5的组
5.4 按多个字段分组,添加排序
SELECTAVG(salary),department_id,job_id
FROM employees
WHERE department_id ISNOTNULLGROUPBY department_id,job_id #department_id,job_id顺序可颠倒HAVINGAVG(salary)>10000ORDERBYAVG(salary)DESC;#查询每个工种每个部门的平均工资,筛选工资大于1W的,并按平均工资降序排序
【等值连接】
① 多表等值连接的结果为多表的交集部分
② n表连接,至少需要n-1个连接条件
③ 多表的顺序没有要求
④ 一般需要为表起别名
⑤ 可以搭配前面介绍的所有子句使用,比如排序、分组、筛选
SELECT last_name,department_name
FROM employees,departments
WHERE employees.department_id=departments.department_id;#查询员工名和对应的部门名
【为表起别名】
① 提高语句的简洁度
② 区分多个重名的字段
注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定!!!
SELECT e.last_name,e.job_id,j.job_title #为表起了别名,则查询的字段就不能使用原来的表名去限定FROM employees e,jobs j #为表起别名WHERE e.`job_id`=j.`job_id`;#job_id两个表都有,需要加限定
【可以添加筛选、分组、排序】
SELECT department_name,d.`manager_id`,MIN(salary)#查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资,按最低工资降序FROM departments d,employees e
WHERE d.`department_id`=e.`department_id`AND commission_pct ISNOTNULL#筛选GROUPBY department_name,d.`manager_id`#分组ORDERBYMIN(salary)DESC;#排序
【三表连接】
SELECT last_name,department_name,city #查询员工名、部门名和所在的s开头的城市FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id`AND d.`location_id`=l.`location_id`AND city LIKE's%'ORDERBY department_name DESC;
【非等值连接】
SELECT salary,grade_level #查询员工的工资和工资级别FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal`AND g.`highest_sal`ORDERBY grade_level;
【自连接】
SELECT
e.employee_id,
e.last_name,
m.employee_id,
m.last_name #查询员工名和上级的名称FROM
employees e,
employees m #利用别名把一个表当成两个表,甚至更多表WHERE e.`manager_id`= m.`employee_id`;
【等值连接】
SELECT`department_name`,COUNT(*) 员工个数 #查询名字中包含e的部门的员工个数>3的部门名和员工个数,并按个数降序FROM`employees` e
INNERJOIN`departments` d
ON e.`department_id`= d.`department_id`WHERE`department_name`LIKE'%e%';GROUPBY e.`department_id`HAVING 员工个数>3ORDERBY 员工个数 DESC;
【三表连接】
SELECT`last_name`,`department_name`,`job_title`#查询员工名、部门名、工种名,并按部门名降序FROM`employees` e #此处千万别加 ',' 好几次错误都在这INNERJOIN`departments` d ON e.`department_id`=d.`department_id`INNERJOIN`jobs` j ON e.`job_id`=j.job_id
ORDERBY d.`department_name`DESC;
【非等值连接】
SELECTCOUNT(*),`grade_level`#查询工资级别的个数>20的个数,并且按工资级别降序FROM`employees` e
JOIN`job_grades` j
ON e.`salary`BETWEEN j.`lowest_sal`AND j.`highest_sal`GROUPBY grade_level
HAVINGCOUNT(*)>20ORDERBY grade_level DESC;
【自连接】
SELECT e.`last_name` 员工,m.`last_name` 领导 #查询姓名中包含字符k的员工的名字、上级的名字FROM`employees` e
JOIN`employees` m
ON e.`manager_id`= m.`employee_id`WHERE e.`last_name`LIKE'%k%'AND m.`last_name`LIKE'%k%';
6.2.2 外连接
应用场景:一个表有,另一个表没有的记录
特点:
1、查询的信息来自的表就是是主表
外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配的值
如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接结果+主表中有而从表没有的记录
2、左外连接,leftjoin 左边的是主表
右外连接,rightjoin右边的是主表
3、左外和右外交换两个表的顺序,可以实现同样的效果
4、全外连接 = 内连接的结果 + 表1中有但表2没有的 + 表2中有但表1没有的
【左外连接】
SELECT d.`department_name`#查询哪个部门没有员工FROM`departments` d
LEFTJOIN`employees` e
ON d.`department_id`= e.`department_id`WHERE e.`department_id`ISNULL;
【全外连接】!!!注意:【MySQL不支持 Oracle支持】
SELECT g.*,b.*FROM girl g
FULLJOIN boys b
ON g.`boyfriend_id`= b.id;#结果没有的部分用null填充
【交叉连接】
SELECT b.*,bo.*FROM beauty b
CROSSJOIN boys bo;#得到一个笛卡尔乘积
特点:
① 子查询放在小括号()内
② 子查询一般放在条件的右侧
③ 标量子查询,一般搭配着单行操作符使用 ><>=<==<>
列子查询,一般搭配着多行操作符使用 in/notin、any/some、all
④ 子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
7.1.2 标量子查询(单列单行子查询)
SELECT last_name,job_id,salary
FROM employees
WHERE salary=(SELECTMIN(salary)FROM employees
);#返回公司工资最少的员工的last_name,job_id和salarySELECTMIN(salary),department_id
FROM employees
GROUPBY department_id
HAVINGMIN(salary)>(SELECTMIN(salary)FROM employees
WHERE department_id =50);#查询最低工资大于50号部门最低工资的部门id和其最低工资
7.1.2 列子查询(单列多行子查询)
说明:
in/notin 等于列表中的任意一个、不等于列表中的任意一个
any/some 和子查询返回的某一个值比较
all 和子查询返回的所有值比较
SELECT last_name
FROM employees
WHERE department_id IN(# in 可换成 =anySELECTDISTINCT department_id # not in 可换成 <>allFROM departments
WHERE location_id IN(1400,1700));#返回location_id是1400或1700的部门中的所有员工姓名SELECT last_name,employee_id,job_id,salary
FROM employees
WHERE salary<ALL(SELECTDISTINCT salary
FROM employees
WHERE job_id ='IT_PROG')AND job_id<>'IT_PROG';#返回其它工种中比job_id为‘IT_PROG’工种所有工资都低的员工的员工号、姓名、job_id、salary
7.1.3 行子查询(一行多列或多行多列、用的少)
SELECT*FROM employees
WHERE employee_id=(SELECTMIN(employee_id)FROM employees
)AND salary=(SELECTMAX(salary)FROM employees
);#查询员工编号最小并且工资最高的员工信息
7.2 select后(标量子查询)
仅支持标量子查询
SELECT d.*,(SELECTCOUNT(*)FROM employees e
WHERE e.department_id = d.`department_id`) 个数
FROM departments d;#查询每个部门的员工个数
7.3 from后(表子查询)
将子查询结果充当一张表,要求【必须起别名】
SELECT ag_dep.*,g.`grade_level`FROM(SELECTAVG(salary) ag,department_id
FROM employees
GROUPBY department_id
) ag_dep
INNERJOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;#查询每个部门的平均工资的工资等级
7.4 exists后(相关子查询)
语法:
exists(完整的查询语句,一般为普通的连接查询)
结果:
查询语句结果有没有,输出1或0
特点:
先外(主)查询后(内)子查询
外查询涉及到子查询的相关字段
#in 查询有员工的部门名SELECT department_name
FROM departments d
WHERE d.`department_id`IN(SELECT department_id
FROM employees
);#exists 查询有员工的部门名SELECT department_name
FROM departments d
WHEREEXISTS(SELECT*FROM employees e
WHERE d.`department_id`=e.`department_id`);
八、分页查询【LIMIT…】
应用场景:如web中,当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
(jointype)join 表2on 连接条件
where 筛选条件
groupby 分组字段
having 分组后的筛选
orderby 排序的字段
limit(offset,)size;offset:要显示条目的起始索引(起始索引从0开始)
size:要显示的条目个数
特点:
① limit语句放在查询语句的最后
② 要显示的页数page,每页的条目数size
limit(page-1)*size,size;SELECT*FROM employees LIMIT5;#从第一条开始,则0可以省略,查询前五条员工信息SELECT*FROM employees LIMIT10,15;#查询第11条——第25条SELECT*FROM employees
WHERE commission_pct ISNOTNULLORDERBY salary DESCLIMIT10;#有奖金的员工信息,并且工资较高的前10名显示出来
九、联合查询【…UNION…】
union 联合\合并:将多条查询语句的结果合并成一个结果
语法:
查询语句1union
查询语句2union...
应用场景:
要查询的结果来自于多个表,且多个表没有直接的连接关系,但【查询的信息一致】时
特点:
1、要求多条查询语句的查询列数是一致的!
2、要求多条查询语句的查询的每一列的类型和顺序最好一致
3、union关键字【默认去重】,如果使用unionall可以包含重复项
SELECT*FROM employees WHERE email LIKE'%a%'UNIONSELECT*FROM employees WHERE department_id>90;#查询部门编号>90或邮箱包含a的员工信息SELECT id,cname FROM t_ca WHERE csex='男'UNIONALLSELECT t_id,tname FROM t_ua WHERE tGender='male';#查询中国用户中男性的信息以及外国用户中年男性的用户信息