mysql查询总结(全)

sql查询总结

数据库建表sql和本文md文档在如下地址:

链接:https://pan.baidu.com/s/1pheKTfktS-9Hf141FwJM3w
提取码:th31

一、基础查询

1. 基础查询语法

1. 查询表中的单个字
SELECT last_name 
FROM employees`

2.查询表中的多个字段
SELECT last_name,salary,email 
FROM employees;

3.查询表中的所有字段 
SELECT * 
FROM employees;

4.查询常量值
SELECT 100;

5.查询表达式
SELECT 100%98;

6.查询函数
SELECT VERSION();

2.起别名(AS,或者空格)

SELECT 100%98 AS 结果
SELECT last_name AS,first_name ASFROM employees;

3.去重(distinct)

SELECT DISTINCT department_id 
FROM employees;

4.+号的作用(+号只能计算数字,concat才是拼接字符串)

  • 案例:查询员工名和姓连接成一个字段,并显示为 姓名
SELECT CONCAT('a','b','c') AS 结果;
SELECT CONCAT(last_name,first_name) AS 姓名	FROM	employees;·

判空 IFNull(str1,str2):如果str1==空,则取str2

SELECT CONCAT(last_name,'老王',first_name,IFNULL(department_id,'我是空')) AS output FROM employees;`

5.基础查询小案例

#1.	下面的语句是否可以执行成功  
SELECT last_name , job_id , salary AS sal
FROM employees; 

#2.下面的语句是否可以执行成功  
SELECT  *  FROM employees; 

#3.找出下面语句中的错误 
SELECT employee_id , last_name,
salary * 12 AS "ANNUAL  SALARY"
FROM employees;

#4.显示表departments的结构,并查询其中的全部数据
DESC departments;
DESC departments;
SELECT * FROM `departments`;

#5.显示出表employees中的全部job_id(不能重复)
SELECT DISTINCT(job_id)	FROM employees;

#6.显示出表employees的全部列,各个列之间用逗号连接,列头显示成OUT_PUT
SELECT CONCAT(employee_id,',',first_name,',',last_name,',',email,',',IFNULL(commission_pct,0)) FROM employees;
	

二、条件查询

1.按条件表达式筛选

> < = != <> >= <=

#案例1:查询工资>12000的员工信息
SELECT * 
FROM employees 
WHERE salary>12000;
	
#案例2:查询部门编号不等于90号的员工名和部门编号
SELECT first_name,department_id 
FROM employees 
WHERE department_id != 90;

2.按逻辑表达式筛选

and or not

#案例1:查询工资z在10000到20000之间的员工名、工资以及奖金
SELECT last_name,salary,commission_pct 
FROM employees 
WHERE salary>10000 AND salary<20000;

#案例2:查询部门编号不是在90到110之间,或者工资高于15000的员工信息
SELECT * 
FROM employees 
WHERE NOT(department_id>=90 AND department_id <=110) OR salary>15000;

3.模糊查询

1.like

like一般搭配通配符使用
通配符:_(只占一个字符)或者&(可占多个字符)

#案例1:查询员工名中包含字符a的员工信息
SELECT * 
FROM employees 
WHERE first_name LIKE '%a%';

#案例2:查询员工名中第三个字符为e,第五个字符为a的员工名和工资
SELECT first_name,salary 
FROM employees 
WHERE first_name LIKE '__e_a';

#案例3:查询员工名中第二个字符为_的员工名
SELECT first_name 
FROM employees 
WHERE first_name LIKE '_$_%' ESCAPE '$';

2.between 1 and100

bewttem 1 and 10
#案例1:查询员工编号在100到120之间的员工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;
不在100-120之间:NOT BETWEEN 100 AND 120;

3.in

in
#案例:查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号
SELECT first_name,job_id FROM employees WHERE	job_id IN ('IT_PROG','AD_VP','AD_PRES');

4. is null(==null)和is not null(!=null)

is nullis not null
#案例1:查询没有奖金的员工名和奖金率
SELECT first_name,commission_pct FROM employees WHERE	commission_pct IS NULL;

#案例1:查询有奖金的员工名和奖金率
SELECT first_name,commission_pct FROM employees WHERE	commission_pct IS NOT NULL;

5.案例练习

#1.查询工资大于 12000 的员工姓名和工资
SELECT first_name,salary 
FROM employees 
WHERE salary>12000;

#2.查询员工号为176的员工姓名的部门号和年薪
SELECT first_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪  
FROM employees 
WHERE employee_id =176;

#3.选择工资不在5000到12000的员工姓名和工资
SELECT first_name,salary 
FROM employees 
WHERE salary NOT BETWEEN 5000 AND 12000;

#4.选择在20或50号部门工作的员工姓名和部门号
SELECT first_name,department_id	
FROM employees 
WHERE department_id =20 OR department_id =50;

#5.选择公司中没有管理者的员工姓名和job_id
SELECT first_name,job_id 
FROM employees 
WHERE manager_id IS NULL;

#6.选择公司中有奖金的员工姓名,工资和奖金级别
SELECT first_name,salary 
FROM employees 
WHERE commission_pct IS NOT NULL;

#7.选择员工姓名的第三个字母是a的员工姓名
SELECT first_name 
FROM employees 
WHERE first_name LIKE '__a%';

#8.选择姓名中有字母a和e的员工姓名
SELECT first_name 
FROM employees 
WHERE first_name LIKE '%a%' AND first_name LIKE '%e%';

#9.显示出表employees中first_name以'e'结尾的员工信息
SELECT * 
FROM employees 
WHERE first_name LIKE '%e';

#10.显示出表employees部门编号在80-100之间的姓名、职位
SELECT first_name 
FROM employees 
WHERE department_id BETWEEN 80 AND 100;

#11.显示出表employees的manager_id 是100,101,110的员工姓名和职位
SELECT first_name,manager_id 
FROM employees 
WHERE manager_id IN ('100','101','110');

三、排序查询(order by)

select name from user where id>0 order by id desc;

执行顺序(排序是放在select后的,因此可以用别名)

  1. from user
  2. where id>0
  3. select name
  4. order by id desc
#1.查询员工的姓名和部门号和年薪,按年薪降序 按姓名升序
SELECT first_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM employees
ORDER BY 年薪 DESC,first_name ASC;

#2.选择工资不在8000到17000的员工的姓名和工资,按工资降序
SELECT first_name,salary
FROM employees
WHERE salary NOT BETWEEN 8000 AND 17000
ORDER BY salary DESC;

#3.查询邮箱中包含e的员工信息,并先按邮箱的字节数降序,再按部门号升序
SELECT * 
FROM employees
WHERE email LIKE '%e%'
ORDER BY LENGTH(email) DESC,department_id ASC;

四、常见函数

常见函数

  1. 字符函数
  2. 数学函数
  3. 日期函数
  4. 流程控制函数

1.字符函数

#1.length 获取参数值的字节个数(1个字=3个字节)
SELECT LENGTH('a老王');

#2.concat 拼接字符串
SELECT CONCAT('hellow,',first_name) 
FROM employees;

#3.upper、lower
#示例:将姓变大写,名变小写,然后拼接
SELECT CONCAT(UPPER(first_name),LOWER(last_name))AS 大小写拼接 
FROM employees;

#4.substr、substring
注意:索引从1开始,截取多少个
#截取从指定索引处后面所有字符
SELECT SUBSTR('爱上是否',3);

#截取从指定索引处指定字符长度的
SELECT SUBSTRING('案说法计划氨基酸客户发jk',1,5);

#案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
SELECT CONCAT(UPPER(SUBSTR(first_name,1,1)),'_',LOWER(SUBSTR(first_name,2))) AS output FROM employees;

#5.instr 返回子串第一次出现的索引,如果找不到返回0
SELECT INSTR('阿萨ask房管局','萨');

#6.trim(去掉头尾空格)
SELECT TRIM('   asf jaskf j    ');

#7.lpad,rpad 用指定的字符实现左填充指定长度()
SELECT LPAD('奥是否快啦',10,'a');

#8.replace 替换
SELECT REPLACE('老王','老','小');

2.数学函数

#1.round 四舍五入
SELECT ROUND(54.6);

#2.ceil 向上取整,返回>=该参数的最小整数
SELECT CEIL(-1.02);

#3.floor 向下取整,返回<=该参数的最大整数
SELECT FLOOR(-9.99);

#4.truncate 截断(数字,从小数点第几位开始截断)
SELECT TRUNCATE(1.69999,1);

#5.mod取余
SELECT MOD(10,-3);

3.日期函数

#now 返回当前系统日期+时间
SELECT NOW();

#curdate 返回当前系统日期,不包含时间
SELECT CURDATE();

#curtime 返回当前时间,不包含日期
SELECT CURTIME();

#可以获取指定的部分,年、月、日、小时、分钟、秒
SELECT YEAR(NOW());
SELECT YEAR('1998-1-1');

#str_to_date 将字符通过指定的格式转换成日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d') AS out_put;
SELECT STR_TO_DATE('2012-09-23 05:54:45','%Y-%m-%d') AS 日期格式化;
#查询入职日期为1992--4-3的员工信息
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');

#date_format 将日期转换成字符
SELECT DATE_FORMAT(NOW(),'%y年%m月%d日') AS out_put;

#查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年') 入职日期
FROM employees
WHERE commission_pct IS NOT NULL;

4.流程控制

#1.if(表达式,成立,不成立)
SELECT IF(salary>5000,'超过5k','没有噢')  FROM employees;

#2.case 表达式
	where 匹配的值 then 输出结果
	
案例:查询员工的工资,要求部门号=30,显示的工资为1.1倍,部门号=40,显示的工资为1.2倍,其他部门,显示的工资为原工资
SELECT salary AS 原始工资,CASE	department_id
	WHEN 30 THEN salary*1.1
	WHEN 40 THEN salary*1.2
	ELSE salary
	END AS 加部门奖金后工资
	FROM employees;

5.分组函数

count()
avg()
sum()
max()
min()
#简单使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;

/**
重点提一下count()
count(*)和count(1)和count(字段名)
count(*)和count(1)效果一样,只不过count(1)在查询的时候先建一个列都为1再统计个数
而count(字段名)则是该列有不空的才统计+1
**/

五、分组查询(需求中包含有每个,各个)

/*
语法:
1.select 查询列表
2.from 表
3.【where 筛选条件】
4.group by 分组的字段
5.【order by 排序的字段】;
执行顺序为:from->where->group by->select>order by (排序是最后)

特点:
1、和分组函数一同查询的字段必须是group by后出现的字段
2、筛选分为两类:分组前筛选和分组后筛选(一般来讲,能用分组前筛选的,尽量使用分组前筛选,提高效率)
				针对的表				位置			连接的关键字
分组前筛选		 原始表				group by前		where	
分组后筛选		 group by后的结果集     group by后	   having

3、分组可以按单个字段也可以按多个字段
4、可以搭配着排序使用
*/

#1.简单的分组
#案例1:查询每个工种的员工平均工资
SELECT AVG(salary) 平均工资,job_id
FROM employees
GROUP BY job_id;


#2、可以实现分组前的筛选
#案例1:查询邮箱中包含a字符的 每个部门的最高工资
SELECT MAX(salary) 最高工资,department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;

#案例2:查询有奖金的每个领导手下员工的平均工资
SELECT AVG(salary) 平均工资,manager_id
FROM employees
WHERE commission_pct IS NULL
GROUP BY manager_id;


#3、分组后筛选
#案例1:查询哪个部门的员工个数>5
SELECT department_id,COUNT(*)
FROM employees
GROUP BY department_id
HAVING COUNT(*)>5;

#案例2:每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
SELECT job_id,MAX(salary) 最高工资
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING 最高工资>12000;

#案例3:领导编号>102的每个领导手下的最低工资大于5000的领导编号和最低工资
SELECT manager_id,MIN(salary) 最低工资
FROM employees
WHERE manager_id>120
GROUP BY manager_id
HAVING 最低工资>5000;


#4.添加排序
#案例:每个工种有奖金的员工的最高工资>6000的工种编号和最高工资,按最高工资升序
SELECT job_id,MAX(salary) 最高工资
FROM employees
WHERE commission_pct IS NOT NULL
GROUP BY job_id
HAVING 最高工资>6000
ORDER BY 最高工资 ASC;

六、连接查询

1.内连接(sql92语法)

(1)等值连接

/*
① 多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③ 多表的顺序没有要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有子句使用,比如排序、分组、筛选
*/
#案例1:查询员工名和对应的部门名
SELECT last_name,department_name
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id`;


#2、为表起别名
/*
①提高语句的简洁度
②区分多个重名的字段
注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定
*/
#查询员工名、工种号、工种名
SELECT e.`first_name`,e.`job_id`,j.`job_title`
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`;


#4、可以加筛选
#案例:查询有奖金的员工名、部门名
SELECT e.`first_name`,d.`department_name`
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id` 
AND e.`commission_pct` IS NOT NULL;


#案例2:查询城市名中第二个字符为o的部门名和城市名
SELECT d.`department_name`,l.`city`
FROM locations l,departments d
WHERE d.`location_id`=l.`location_id` 
AND l.`city` LIKE '_o%';


#5、可以加分组
#案例1:查询每个城市的部门个数
SELECT COUNT(1),l.`location_id`
FROM departments d,locations l
WHERE d.`location_id`=l.`location_id`
GROUP BY l.`location_id`;


#案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
SELECT d.`department_name`,d.`manager_id`,MIN(e.`salary`)
FROM employees e,departments d
WHERE e.`department_id`=d.`department_id` 
AND e.`salary` IS NOT NULL
GROUP BY d.`department_id`;


#6、可以加排序
#案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
SELECT j.`job_title`,COUNT(1)
FROM employees e,jobs j
WHERE e.`job_id`=j.`job_id`
GROUP BY j.`job_id`
ORDER BY COUNT(1);


#7、可以实现三表连接?
#案例:查询员工名、部门名和所在的城市
SELECT e.`first_name`,d.`department_name`,l.`city`
FROM employees e,departments d,locations l
WHERE e.`department_id`=d.`department_id` 
AND d.`location_id`=l.`location_id`;

(2)非等值连接

#案例1:查询员工的工资和工资级别
SELECT e.`first_name`,j.`grade_level`
FROM employees e,job_grades j
WHERE e.`salary` BETWEEN j.`lowest_sal`AND j.`highest_sal`;

(3)自连接(一般用于分级查询商品一级分类,二级分类,连接自身表)

#案例:查询 员工名和上级的名称
SELECT e.`first_name` 员工名称,e2.`first_name` 领导名称
FROM employees e,employees e2
WHERE e.`manager_id`=e2.`employee_id`;

2.内连接(sql99语法)

/**
相比92语法多了:[连接类型] join 表1 on 条件
语法:
SELECT 
FROM 表1
INNER JOIN 表2 on 条件;
**/
#查询员工名、工种号、工种名
SELECT e.`first_name`,j.`job_id`,j.`job_title`
FROM employees e
INNER JOIN jobs j ON e.`job_id`=j.`job_id`	

3.外连接

外连接:查询结果为主表中所有的记录。如果从表有匹配项,则显示匹配项,如果从表中没有匹配项,则显示为Null
应用场景:一般用于查询主要中有但是从表中没有的记录

(1)左外连接

#1.显示所有员工的姓名,部门号和部门名称。
SELECT e.`first_name`,d.`department_id`,d.`department_name`
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`;

#2.查询90号部门员工的job_id和90号部门的location_id
#结果:部门id 员工job_id job_id location_id
SELECT d.`department_id`,e.`job_id`,d.`location_id`
FROM departments d
LEFT JOIN employees e ON d.`department_id`=e.`department_id`
WHERE d.`department_id`=90;

#3.选择所有有奖金的员工的 last_name , department_name , location_id , city
SELECT e.`last_name`,d.`department_name`,l.`location_id`,l.`city`
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`
LEFT JOIN locations l ON d.`location_id`= l.`location_id`
WHERE e.`commission_pct` IS NOT NULL;

#4.选择city在Toronto工作的员工的 last_name , job_id , department_id , department_name 
SELECT e.`last_name`,e.`job_id`,d.`department_id`,d.`department_name`
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`
LEFT JOIN locations l ON d.`location_id`= l.`location_id`
WHERE l.`city`='Toronto';

#5.查询每个工种、每个部门的部门名、工种名和最低工资
SELECT d.`department_name`,j.`job_title`,MIN(e.`salary`)
FROM employees e
LEFT JOIN departments d ON e.`department_id`=d.`department_id`
LEFT JOIN jobs j ON e.`job_id`=j.`job_id`
GROUP BY e.`job_id`,e.`department_id`

(2)右外连接

使用right join关键字,和左外类似。

(3)全外连接(mysql不支持)

两张表互连,匹配的显示信息,不匹配的显示为Null

4.总结连表查询

image-20200603163500970

七、子查询(最难***)

/*
含义:
出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询

分类:
按子查询出现的位置:
	select后面:
		仅仅支持标量子查询
	
	from后面:
		支持表子查询
		
	where或having后面:★
		标量子查询(单行) √
		列子查询  (多行) √
		行子查询
		
	exists后面(相关子查询)
		表子查询
按结果集的行列数不同:
	标量子查询(结果集只有一行一列)
	列子查询(结果集只有一列多行)
	行子查询(结果集有一行多列)
	表子查询(结果集一般为多行多列)
*/

1.跟在where/having后

特点:
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般搭配着单行操作符使用
> < >= <= = <>

列子查询,一般搭配着多行操作符使用
inany/someall

④子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果

*/
#1.标量子查询★

#案例1:谁的工资比 Abel 高?

#①查询Abel的工资
#②查询员工的信息,满足 salary>①结果
SELECT last_name
FROM employees
WHERE salary>(
            SELECT salary
            FROM employees
            WHERE last_name='Abel');


#案例2:返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id 和工资

#①查询141号员工的job_id
#③查询员工的姓名,job_id 和工资,要求job_id=①并且salary>②
SELECT first_name,job_id,salary
FROM employees
WHERE job_id=(
            SELECT job_id
            FROM employees
            WHERE employee_id=141)
AND salary>(
            SELECT salary
            FROM employees
            WHERE employee_id=143);



#案例3:返回公司工资最少的员工的last_name,job_id和salary
SELECT last_name,job_id,salary
FROM employees
WHERE salary=(
            SELECT MIN(salary)
            FROM employees);


#案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资
#①查询50号部门的最低工资
#②查询每个部门的最低工资
#③ 在②基础上筛选,满足min(salary)>①
#③ 在②基础上筛选,满足min(salary)>①
SELECT department_id,MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary)>(
                    SELECT MIN(salary)
                    FROM employees
                    WHERE department_id=50);

#2.列子查询(多行子查询)★
#案例1:返回location_id是1400或1700的部门中的所有员工姓名
#①查询location_id是1400或1700的部门编号
#②查询员工姓名,要求部门号是①列表中的某一个
SELECT first_name
FROM employees
WHERE department_id IN(
                    SELECT DISTINCT d.`department_id`
                    FROM departments d
                    WHERE d.`location_id` IN(1400,1700));

2.跟在select后

SELECT (
	SELECT department_name,e.department_id
	FROM departments d
	INNER JOIN employees e
	ON d.department_id=e.department_id
	WHERE e.employee_id=102
) 部门名;

3.跟在from后面

/*
将子查询结果充当一张表,要求必须起别名
*/

#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资
#②连接①的结果集和job_grades表,筛选条件平均工资 between lowest_sal and highest_sal
SELECT  ag_dep.*,g.`grade_level`
FROM (
	SELECT AVG(salary) ag,department_id
	FROM employees
	GROUP BY department_id
) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;

4.跟在exists后面

#案例1:查询有员工的部门名
SELECT department_name
FROM departments d
WHERE EXISTS(
	SELECT *
	FROM employees e
	WHERE d.`department_id`=e.`department_id`
);

八、分页查询

/*

应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
	select 查询列表
	from 表
	【join type join 表2
	on 连接条件
	where 筛选条件
	group by 分组字段
	having 分组后的筛选
	order by 排序的字段】
	limit 【offset,】size;
!!执行顺序:from->join->on->where->group by->having->select->order by->limit
	
	offset要显示条目的起始索引(起始索引从0开始)
	size 要显示的条目个数
特点:
	①limit语句放在查询语句的最后
	②公式
	要显示的页数 page,每页的条目数size
	
	select 查询列表
	from 表
	limit (page-1)*size,size;
	
	size=10
	page  
	1	0
	2  	10
	3	20
	
*/
#案例1:查询前五条员工信息
SELECT * FROM  employees LIMIT 0,5;
SELECT * FROM  employees LIMIT 5;

#案例2:查询第11条——第25条
SELECT * FROM  employees LIMIT 10,15;

#案例3:有奖金的员工信息,并且工资较高的前10名显示出来
SELECT * 
FROM employees 
WHERE commission_pct IS NOT NULL 
ORDER BY salary DESC 
LIMIT 10;

九、union联合查询

#进阶9:联合查询
/*
union 联合 合并:将多条查询语句的结果合并成一个结果

语法:
查询语句1
union
查询语句2
union
...


应用场景:
要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时

特点:★
1、要求多条查询语句的查询列数是一致的!
2、要求多条查询语句的查询的每一列的类型和顺序最好一致
3、union关键字默认去重,如果使用union all 可以包含重复项

*/


#引入的案例:查询部门编号>90或邮箱包含a的员工信息
SELECT * FROM employees WHERE email LIKE '%a%' OR department_id>90;

SELECT * FROM employees  WHERE email LIKE '%a%'
UNION
SELECT * FROM employees  WHERE department_id>90;

#案例:查询中国用户中男性的信息以及外国用户中年男性的用户信息
SELECT id,cname FROM t_ca WHERE csex='男'
UNION ALL
SELECT t_id,tname FROM t_ua WHERE tGender='male';

猜你喜欢

转载自blog.csdn.net/laowang__/article/details/106530758
今日推荐