MySQL_基础+高级篇- 数据库 -sql -mysql教程_mysql视频_mysql入门_尚硅谷

1_12mysql的常见命令

DBMS分为两类:
	-基于共享文件系统的DBMS(Access)
	-基于客户机-服务器的DBMS(MySql,Oracle,sqlserver)

mysql的启动和停止服务:
	停止mysql服务:
		net stop mysql

	启动mysql服务:
		net start mysql

mysql的登陆和退出:
	进入mysql:
		mysql -h localhost -P 3306 -u root -p111(111是我设置的密码)
										并且-p和密码之间不能有空格
		mysql -u -p111(这样也可以)
		mysql [-h主机名 -P端口号] -u用户名 -p密码 
				本机可省略
	退出mysql:
		exit和quit


mysql的常见命令汇总:
	1.查看当前所有的数据库
		show databases;
	2.打开指定的库
		use databases;
	3.查看当前库的所有表
		show tables
	4.查看其它库的所有表
		show tables from 库名;
	5.创建表
		create table 表名(
			列名 列类型,
			列名 列类型,
			...
		);
	6.查看表结构
		desc 表名
	7.查看服务器的版本
		mysql>select version();
mysql的常见命令:
	show databases;(mysql命令以分号结尾)
		+--------------------+
		| Database           |
		+--------------------+
		| information_schema |(保存原数据信息)
		| mysql              |(
		| performance_schema |(性能信息)
		| test               |(空的没有表)
		+--------------------+

	use test(指定的库名);
		Database changed

	show tables;

	show tables from mysql;(并没有进入mysql库)
		()		(数据库名称)
		+---------------------------+
		| Tables_in_mysql           |
		+---------------------------+
		| columns_priv              |
		| db                        |
		| event                     |
		| func                      |
		| general_log               |
		| help_category             |
		| help_keyword              |
		| help_relation             |
		| help_topic                |
		| host                      |
		| ndb_binlog_index          |
		| plugin                    |
		| proc                      |
		| procs_priv                |
		| proxies_priv              |
		| servers                   |
		| slow_log                  |
		| tables_priv               |
		| time_zone                 |
		| time_zone_leap_second     |
		| time_zone_name            |
		| time_zone_transition      |
		| time_zone_transition_type |
		| user                      |
		+---------------------------+

	select database();<<查看当前所在的库>>
		+------------+
		| database() |
		+------------+
		| test       |
		+------------+
		1 row in set (0.00 sec)

				(表名自己定义)
	create table stuinfo(
		->id int,
		->name varchar(20));

		Query OK, 0 rows affected (0.02 sec)

		show tables;
			+----------------+
			| Tables_in_test |
			+----------------+
			| stuinfo        |
			+----------------+
			1 row in set (0.00 sec)

	desc stuinfo;(看表的结构)
		+-------+-------------+------+-----+---------+-------+
		| Field | Type        | Null | Key | Default | Extra |
		+-------+-------------+------+-----+---------+-------+
		| id    | int(11)     | YES  |     | NULL    |       |
		| name  | varchar(20) | YES  |     | NULL    |       |
		+-------+-------------+------+-----+---------+-------+
		2 rows in set (0.02 sec)
		
	select * from stuinfo;(*代表所有,及所有存在于stuinfo的数据)
		Empty set (0.00 sec)

	
	insert into stuinfo(id,name) values(2,'rose');
		+------+------+
		| id   | name |
		+------+------+
		|    1 | john |
		|    2 | rose |
		+------+------+
		2 rows in set (0.00 sec)

	update stuinfo set name='lilei' where id=1;
		+------+-------+
		| id   | name  |
		+------+-------+
		|    1 | lilei |
		|    2 | rose  |
		+------+-------+
		2 rows in set (0.01 sec)

	delete from stuinfo where id=1;
		+------+------+
		| id   | name |
		+------+------+
		|    2 | rose |
		+------+------+
		1 row in set (0.00 sec)

	select version();(查看mysql的版本)
		+-----------+
		| version() |
		+-----------+
		| 5.5.62    |
		+-----------+
		1 row in set (0.00 sec)

========================================================================================================================================================================================================================================================================

2_15mysql语法规范介绍

mysql
	1.不区分大小写,但建议关键字大写,表名,列名小写
	2.每条命令最好用分号结尾
	3.每条命令根据需要,可以缩进,换行
	4.注释
		--单行注释:#注释文字
		--单行注释:-- 注释文字(注意有空格)
		--多行注释:/* 注释文字 */

========================================================================================================================================================================================================================================================================

3_17图形化用户界面客户端的介绍

在这里插入代码片

========================================================================================================================================================================================================================================================================

4_18四种表达介绍


employees  员工表
	栏位:
		employee_id int(6)                 员工编号
		first name, varchar (20), Nullable        名
		last name, varchar(25), Nullable        姓
		email, varchar(25), Nullable            邮箱
		phone number, varchar(20), Nullable    电话号码
		job id, varchar(10) Nullable    工种编号
		salary, double(10,2), Nullable        月薪
		commission pct, double(4, 2), Nullable    奖金率
		manager id, int(6), Nullable        上级领导的员工编号
		department_id, int(4), Nullable    部门编号
		hiredate, datetime, Nullable    入职日期

departments  部门表
	栏位
		department_id, int(4)   部门编号
		department name, varchar(3), Nullable  部门名称
		manager id int(), Nullable  部门领导的员工编号
		location id, int(4), Nullable  位置编号

locations 位置表
	栏位
		location id, int(11)        位置编号
		street_ address, varchar(40), Nullable    街道
		postal_code, varchar(12), Nullable    邮编
		city, varchar(30), Nullable    城市
		state province, varchar(25), Nullable 州/省
		country_id, varchar(2), Nullable    国家编号


jobs              工种
	栏位
job_id, varchar(10)    工种编号   
job_title, varchar(35), Nullable    工种名称
min salary, int(6), Nullable    最低工资
max salary, int(6), Nullable    最高工资

========================================================================================================================================================================================================================================================================

5_基础查询介绍

进阶1:基础查询
语法:
    select 查询列表 from 表名;

特点:
    --查询列表可以是:表中的字段,常量值,表达式,函数
    --查询的结果是一个虚拟的表格(相当于java中的System.out.println("字符串")只是单纯的输出

查询表中字段:
    1.查询表中的单个字段(输出结果为last_name所在列的所有属性)
        SELECT last_name FROM employees;
    2.查询表中的多个字段
        SELECT last_name,salary,email FROM employees;
    3.查询标准的所有字段
        SELECT * FROM employees;


    5.查询时的细节
        
        上面并没有写use myemployees
        进入myemployees库
        是因为已经通过软件点击进入了

        --`(着重符)不是'(单引号),`是用来表示一个字段的

        --如何执行命令:   
            你需要通过鼠标,对代码进行选中,然后运行选中代码


查询常量
    1.查询常量值
        SELECT 100;
        SELECT 'john';
    
    2.查询表达式
        SELECT 100%98;

    3.查询函数(方法)
        SELECT    VERSION();(查询当前mysql的版本)


7.起别名
    好处:
        --方便理解,提高可读性
        --如果要查询的字段有重名情况,使用别名可以区分开来
    方式一:
        SELECT first_name AS,last_name ASFROM employees;
    方式二:
        SELECT first_name 姓,last_name 名 FROM employees;
    案例:查询salary,显示结果为out put
        SELECT salary AS `out put` FROM employees;
        SELECT salary AS 'out put' FROM employees;
        SELECT salary AS "out put" FROM employees;
        这三个好像都行没看出来区别

在这里插入图片描述

========================================================================================================================================================================================================================================================================

6_24去重

去重:
案例:查询员工表中涉及到的所有的部门编号
SELECT DISTINCT department_id FROM employees;
加号的作用(+)
java中的加号:
--运算符:
两个操作数都为数值型
--连接符:
只要有一个操作数为字符串
mysql中的+号:
仅仅只有一个功能:运算符
--SELECT 100+50;--SELECT '123'+90;(其中一方为字符型,试图将字符型数值转换为数值型
           如果转换成功,则继续做加法运算)
--SELECT 'JOHO'+90;        如果转换失败,则将字符型数值转换成0)
  SELECT null+10;          如果其中一方为null,则结果肯定为null)
在mysql中对于字符串的拼接采用 concat

案例:查询员工名和姓氏连接成一个字段,并显示为姓名
SELECT CONCAT(first_name,last_name) AS 姓名
FROM employees;

========================================================================================================================================================================================================================================================================

7_27<<案例详解>>基础查询



测试1.下面的语句是否可以执行成功
              select last_name, job_id, salary as sal
              from employees;
执行可以通过,只将salary换名成sal
SELECT last_name AS a, job_id AS job, salary AS sal
FROM employees;        (这样也行)
2.下面的语句是否可以执行成功

               select *from employees;
可以执行成功,employees为表 *匹配的是表中所有的列
这样不可以:
select * from myemployees;
myemployees为数据库,想要看数据库中的表
使用:
show tables;
3.找出下面语句中的错误
select employee_id, last_name,
salary *12 AS "ANNUAL SALARY"
from employees;
4.显示表 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,phone_number,
job_id,salary,commission_pct,manager_id,department_id,hiredate) AS OUT_PUT
FROM employees;
结果有许多为空,原因在于有一列包含许多空值,导致运算时结果为null
更改代码



SELECT last_name AS a, job_id AS job, salary AS sal
FROM employees;

#错误代码,想要查看数据库中的表直接show tables;
#select * from myemployees;

SHOW TABLES;

SELECT employee_id, last_name,
	salary *12 AS "ANNUAL SALARY"
FROM employees;



#departments是表
#想要看表的结构无法使用show
SELECT * FROM departments;

#上面相当于直接把表输出来了
#但是我只想要看他的结构
DESC departments;


#查询表中的全部数据
SELECT * FROM departments;


#输出employees中的全部 job_id
SELECT job_id FROM employees;

#输出employees中的全部 job_id且不重复
SELECT DISTINCT job_id FROM employees;


#显示出表 employees的全部列
SELECT * FROM employees;

#显示出表 employees的全部列,各个列之间用逗号连接,列头显示成OUT_PUT

SELECT CONCAT(employee_id,first_name,last_name,email,phone_number,
	job_id,salary,commission_pct,manager_id,department_id,hiredate) AS OUT_PUT
FROM employees;

#如果为null,则将其对应的值改为0
SELECT IFNULL(commission_pct,0) FROM employees;

SELECT CONCAT(employee_id,first_name,last_name,email,phone_number,
	job_id,salary,IFNULL(commission_pct,0),IFNULL(manager_id,0),department_id,hiredate) AS OUT_PUT
FROM employees;

========================================================================================================================================================================================================================================================================

8_28条件查询介绍


/*
	语法:
		select 
			查询列表
		from
			表名
		where
			筛选条件;(可以理解为,满足筛选就是我可以到的地方(可以输出))
			
	执行顺序:
		1.首先from表名,这是最外层确定表是否存在
			如果存在则将定位到表
		2.where 筛选条件
			看一下那些行满足条件
		3.select查询列表
			得到想要的列
			
	分类:
		--按条件表达式筛选:	
			条件运算符:> < = !=(<>也可以这样写) >= <=
		--按逻辑表达式筛选:
			逻辑运算符:&& || !
					and or not
		--模糊查询
			like
			between and
			in
			is null
		
*/

#一.按条件表达式筛选:
	#案例1:查询工资>12000的员工姓名
SELECT CONCAT(first_name,last_name) AS 姓名
FROM employees
WHERE (salary>12000);


	#案例2:查询部门编号不等于90号的员工名和部门编号
SELECT CONCAT(first_name,last_name) AS 姓名,department_id AS 部门编号
FROM employees
WHERE department_id!=90;


#二.按逻辑表达式筛选
	#案例1:查询工资在10000到20000之间的员工名,工资,以及奖金
SELECT CONCAT(first_name,last_name) AS 姓名,salary,`commission_pct`
FROM employees
WHERE (salary>=10000 AND salary<=20000);

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


#三.模糊查询
/*
	like
		特点:
			1.一般和通配符搭配使用
		通配符:
			%任意多个字符,包含0个字符
			_任意单个字符
	between and 
		1.使用包含between and可以提高语句的简洁度
		2.包含临界值
		3.两个临界值小的在前,大的在后
	in
		1.判断某字段的值是否属于in列表中的某一项
		2.使用in提高语句简洁度
		3.in列表的值类型(必须统一或兼容)
		4.in列表中不支持通配符(因为不是like(像)而是in(等于))
	if null/if not null
		1.=不能判断null值
		2.is后只支持null,并不支持其他
*/


#like
	#案例1:查询员工名中包含字符a的员工信息
SELECT *
FROM employees
WHERE (last_name LIKE "%a%");
	#案例2:查询员工名中第三个字符为a的,第五个字符为a的员工名和工资
SELECT CONCAT(first_name,last_name) AS 名字,salary
FROM employees
WHERE (CONCAT(first_name,last_name) LIKE "__e_a%");

	#案例3:查询员工名中第二个字符为_的员工名
SELECT last_name
FROM employees
WHERE (last_name LIKE "_\_%");
	#案例3还可以这样
SELECT last_name
FROM employees
WHERE (last_name LIKE "_a_%" ESCAPE "a");#自己指定转义字符

#between and
	#案例1:查询员工比那好在100到120之间的员工信息
SELECT *
FROM employees
WHERE (`employee_id` BETWEEN 100 AND 120);

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


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


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


#安全等于(<=>)
	#案例1:查询没有奖金的员工名和奖金率
SELECT last_name,commission_pct
FROM employees
WHERE  commission_pct <=>NULL;

	#案例1:查询工资为12000的员工名和工资
SELECT last_name,salary
FROM employees
WHERE  salary<=>12000;

========================================================================================================================================================================================================================================================================

9_条件查询题目

SELECT *
FROM employees;

								#测试
#1.查询工资大于12000的员工姓名和工资
SELECT `last_name`,
		`salary`
FROM employees
WHERE (salary>12000);


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


#3.选择工资不在5000到 12000的员工的姓名和工资
SELECT `last_name`,
		`salary`
FROM employees
WHERE (salary<5000 OR salary>12000);

#4.选择在20或50号部门工作的员工姓名和部门号。
SELECT `last_name`,`department_id`
FROM employees
WHERE (`department_id`=20 OR `department_id`=50);
#5.选择公司中没有管理者的员工姓名及job_id,管理者
SELECT `last_name`,`job_id`,`manager_id`
FROM employees
WHERE (`manager_id` IS NULL);


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


#7. 选择员工姓名的第三个字母是a的员工姓名
SELECT `last_name`
FROM employees
WHERE (`last_name` LIKE "__a%");
#8.选择姓名中有字母a和e的员工姓名
SELECT `last_name`
FROM employees
WHERE (`last_name` LIKE "%a%e%"  OR `last_name` LIKE "%e%a%");
#9. 显示出表employees表中first_name,以'e'结尾的员工信息
SELECT *
FROM employees
WHERE (`first_name` LIKE "%e");
#10.显示出表employees部门编号在80-100之间的姓名、职位
SELECT `last_name`,`job_id`,`department_id`
FROM employees
WHERE (`department_id` BETWEEN 80 AND 100);
#11.显示出表employees 的manager_id是100,101,110的员工姓名、职位
SELECT `last_name`,`job_id`
FROM employees
WHERE (`manager_id` IN (100,101,110));

============================================================================================================================================================================================================================

10_排序查询

#进阶3:排序查询
SELECT *
FROM `employees`;#会将数据以原始存储形式输出

/*
	如果我想要他按工资顺序进行排序应该怎么办呢?
		--如果使用的是软件,可以直接点击字段(列)
		--如果使用的是cmd命令,可以采用sql语句
*/


/*
	语法:
		select 查询列表
		from 表
		where 筛选条件   <<这几个代码执行结束,想要的东西就出来了>>
		order by 排序列表 [asc|desc]
	
	
	特点:
		1.asc代表升序,desc代表降序
			如果不写,默认为升序
			
	*****order by:
		--oredr by可以支持单个字段,多个字段,表达式,函数,别名
		--order by子句一般是放在查询语句的最后面,limit子句除外
*/


#案例1:查询员工信息,要求工资从高到低排序
SELECT *
FROM `employees`
ORDER BY `salary` DESC;



#案例2:查询员工信息,要求工资从低到高排序
SELECT *
FROM `employees`
ORDER BY `salary` ASC;#这里的asc可要可不要,默认从小到大排序



#案例3:查询部门编号>=90员工信息,按入职时间的先后进行排序
SELECT *
FROM `employees`
WHERE (`department_id`>=90)
ORDER BY `hiredate`;


#案例4:按年薪的高低显示员工的信息和年薪[按表达式排序]
SELECT *,`salary`*12*(1+IFNULL(`commission_pct`,0)) AS 年薪
FROM `employees`
ORDER BY `salary`*12*(1+IFNULL(`commission_pct`,0)) DESC;




#案例5:按年薪的高低显示员工的信息和年薪[按别名排序]
SELECT *,`salary`*12*(1+IFNULL(`commission_pct`,0)) AS 年薪
FROM `employees`
ORDER BY 年薪 DESC;


#案例6:按姓名的长度显示员工的姓名和工资[按函数排序]
SELECT `last_name`,`salary`
FROM `employees`
ORDER BY LENGTH(`last_name`);


#案例7:查询员工信息,要求先按工资排序,再按员工编号排序[按多个字段排序]
SELECT *
FROM `employees`
ORDER BY `salary`,`employee_id`;#这个第二个排序肯定不是直接再将数据排一遍
#他是在原有的基础上,相等数据之间再次进行排序
		






####p42_排序查询案例详解

#1.查询员工的姓名和部门号和年薪,按年薪降序按姓名升序
SELECT `last_name`,
		`department_id`,
		`salary`*12*(1+IFNULL(`commission_pct`,0)) AS 年薪   
FROM `employees`
ORDER BY 年薪 DESC,`last_name`;#注意这个是按姓名升序,应该和python一样比较方式

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



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

============================================================================================================================================================================================================================

11_43常见函数介绍

#进阶4:常见函数

/*
	概念:类似于java中的方法,python的函数,将具有特定功能的代码封装,函数名是
		这段代码的入口,在使用时只需调用函数名即可
	好处:
		1.隐藏了实现细节
		2.提高了代码的重用性
	调用:
		select 函数名(实参列表) from 表;如果函数中所需元素使用到表中元素
	注意:
		--记住叫什么(函数名)
		--记住干什么(函数功能)
		
	分类:
		1.单行函数
			concat,length,ifnull
		2.分组函数
			功能:做统计使用,又称为统计函数,聚合函数,组函数
*/


============================================================================================================================================================================================================================

12_45字符函数

#字符函数
/*
	1.length 获取参数值的字节个数
	2.concat 拼接字符
*/

############1.length
SELECT LENGTH('aaa');#三个字节(注意这里是字节长度,及在计算机内存的存储大小,不是字符长度)
SELECT LENGTH('张三丰aada');#13个字节(utf-8编码问题)

############2.concat
SELECT CONCAT(`first_name`,'_',`last_name`) AS a
FROM `employees`;


############3.upper,lower(全部大写,全部小写)
SELECT UPPER(`last_name`)
FROM `employees`;

SELECT LOWER(`last_name`)
FROM `employees`;

	#实例:将姓变大写,名变小写,然后拼接
SELECT CONCAT(UPPER(`first_name`),'_',LOWER(`last_name`)) AS 姓名
FROM `employees`;


############4.substr(substring,这两个是一样的一个简写,一个全写)
#substr函数使用了如同Java中方法重载一样的机制
	#相同函数名,通过参数的不同进行不同的调用
#注意:
	#整个sql语言中索引从1开始
SELECT SUBSTR('abcdefghijkl',6);#fghijkl输出指定位置往后的元素(包括指定位置)


SELECT SUBSTR('abcdefghijkl',2,3);#bcd这里的3是指三个字符长度

SELECT SUBSTR('abcdefghijkl' FROM 10);#jkl好像和第一个没啥区别,都是从当前位置输出

SELECT SUBSTR('abcdefghijkl' FROM 2 FOR 3);#bcd


#看似有4种方法,但按照功能划分只有两种



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



############5.instr
#返回字符串的子串在该字符串中的起始索引
#他是从左到右寻找,找到第一个就直接输出了
#找不到输出0

#现在字符串的匹配算法应该都是KMP????
SELECT INSTR('abcdefghijkl','abc');#1

SELECT INSTR('abcabc','abc');#1

SELECT INSTR('abcabc','e');#0



############6.trim
#去掉前后空格
#不去掉中间的
#跟python中的str.strip()很像,功能很相似一样
#但不得不说strip还是强一些,如80行(第4个)
#strip不会给他识别成一个整体,而是分成了两个字符
#所以如果使用strip得到的结果为:奈斯奈斯aaa奈斯

SELECT LENGTH(TRIM('     a      '));#1
SELECT LENGTH(TRIM('  a  a  a  a '));#10

SELECT TRIM('a' FROM 'aaaa奈斯奈斯aaa奈斯aaa');#奈斯奈斯aaa奈斯

SELECT TRIM('ab' FROM 'aaabbaaaa奈斯奈斯aaa奈斯aaabb');#ab被看成一个整体进行比较



############7.lpad 用指定字符进行左填充得到指定长度
SELECT LPAD('真理之门前的小丑',15,'1');

SELECT LPAD('真理之门前的小丑',15,'');#null

SELECT LPAD('真理之门前的小丑',15,' ');#空格填充

SELECT LPAD('真理之门前的小丑',15);#没有默认填充,必须给参数

SELECT LPAD('真理之门前的小丑',2,'1');#超出的长度会被截断




############8.rpad
SELECT RPAD('真理之门前的小丑',15,'ab');



############9.replace 替换
#这个替换是对所有的
SELECT REPLACE('我我我我你你你你你我我我','我','你');

============================================================================================================================================================================================================================

13_46数学函数

#数学函数

############1.round 四舍五入
#无论正数还是负数,先去绝对值,四舍五入后再把符号带上
#这个函数也有方法的重载
SELECT ROUND(1.65);#2
SELECT ROUND(-1.44);#-1
SELECT ROUND(-1.65);#-2

SELECT ROUND(1.657,2);#1.66保留两位小数
SELECT ROUND(-1.9093,3);#1.909



############2.ceil  向上取整,返回大于等于他的最小整数
SELECT CEIL(1.234);#2
SELECT CEIL(1.000);#1,大于等于他的最小整数是他自己
SELECT CEIL(-1.000);#-1
SELECT CEIL(-101.100);#-101


############3.floor  向下取整,返回小于等于该参数的最大整数

SELECT FLOOR(1.01);#1
SELECT FLOOR(-1.01);#-2


############4.truncate 截断,无论后面写的是啥,直接pass掉
SELECT TRUNCATE(1.123349,5);#1.12334


############5.mod  取余
#mod(n,m)  n-n/m*m=余数,这里n/m是整数,n是m的多少倍,可能会剩下一些非0数
#这个非0数就是余数,用原来的n减一下就好了
SELECT MOD(10,3);#1
SELECT MOD(-10,3);#-10-3*(-3)=-1
SELECT MOD(10,-3);#10-(-3)*(-3)=1

SELECT 10%-3;  #mod和这玩意是一样的

============================================================================================================================================================================================================================

14_47日期函数

#日期函数

#1.now 返回当前系统日期+时间
SELECT NOW();#2021-09-23 17:35:24


#2.curdate 返回当前系统日期,不包含时间
SELECT CURDATE();#2021-09-23


#3.curtime 返回当前的时间,不包含日期
SELECT CURTIME();#17:38:27



#4.可以获取指定的部分,年,月,日,小时,分钟,秒
	#年
SELECT YEAR(NOW());#2021
SELECT YEAR('1991,2021');#应该是无法识别,以为你给的里面没有
SELECT YEAR('1991-1011-1');#哈哈,月份出的有问题
SELECT YEAR('1991-10-1');#1991

SELECT YEAR(`hiredate`)
FROM `employees`
ORDER BY YEAR(`hiredate`);


	#月
SELECT MONTH(NOW());#9
SELECT MONTHNAME(NOW());#September

	#日
SELECT DAY(NOW());#23
SELECT DAYNAME(NOW());#Thursday,星期4


	#小时
SELECT HOUR(NOW());#17
#select horname(now()) 没这玩意


	#分钟
SELECT MINUTE(NOW());#59
#select minutename(now()); 报错


	#秒
SELECT SECOND(NOW());#16
#select secondname(now()); 报错


	

#5.str_to_date 将日期格式的字符转换成指定格式的日期
SELECT STR_TO_DATE('1991-10-1','%Y-%m-%d');#1991-10-01
#上面可能看不出来什么
SELECT STR_TO_DATE('1-10-1991','%d-%m-%Y');#1991-10-01
SELECT STR_TO_DATE('1-10-1991','%d-%m-%y');#2019-10-01
#注意mysql虽然不区分大小写,但是像这种字符的匹配,是需要注意格式的



/*	序号				格式符						功能
	----------------------------------------------------------
	1					%Y							四位的年份
	2					%y							2位的年份
	3					%m							月份(01,02,...11,12)
	4					%c							月份(1,,2,....11,12)
	5					%d							日(01,02,.......)
	6					%H							小时(24小时制)
	7					%h							小时(12小时制)
	8					%i							分钟(00,01,...59)
	9					%s							秒(00,01,...59)

*/


#查询入职日期为1992-4-3的员工信息(为了方便这里只输出入职时间信息)
SELECT `hiredate`
FROM `employees`
WHERE (YEAR(`hiredate`)='1992-4-3');#哈哈哈 mysql的=就是判断


SELECT `hiredate`
FROM `employees`
WHERE (`hiredate`='1992-4-3');#哈哈哈 mysql的=就是判断
#这样也能判断,不知道为什么?


SELECT `hiredate`
FROM `employees`#将用户输入的不正确,不好的格式,转化成好的
WHERE (`hiredate`=STR_TO_DATE('4-3 1992','%m-%d %Y'));


SELECT STR_TO_DATE('4-3 1992','%m-%d %Y');#1992-04-03 转化为标准形式






#6.date_format:将日期转换成字符
SELECT DATE_FORMAT('2018/10/1',"%Y年%m月%d日");#2018年10月1日
SELECT DATE_FORMAT('2018/10/1',"%y年%m月%d日");#18年10月01日

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

============================================================================================================================================================================================================================

15_48其他函数

#其他函数

#当前mysql版本
SELECT VERSION();#5.5.62

#当前所在数据库
SELECT DATABASE();#myemployees

#当前用户
SELECT USER();#root@localhost

============================================================================================================================================================================================================================

16_流程控制函数

#流程控制函数
#if函数:if else效果


#相当于三元运算符 (条件表达式)?表达式1:表达式2;
SELECT IF(10<5,'大','小');#小

SELECT `last_name`,`commission_pct`,
	IF(`commission_pct` IS NULL,'没奖金,哈哈','有奖金,嘻嘻')
FROM `employees`;



#2.case函数的使用一:类似于java中的switch case 的效果
/*
	switch(变量或表达式){
		case 常量1:语句1 break;#如果没有break会直接执行后面的而不进行判断
		case 常量2:语句2 break;
		case 常量3:语句3 break;
		default:语句n;break;
	}
	
	mysql中
	case要判断字段或表达式
	when 常量1 then 要显示的值1或语句1;(语句加分号,值不需要分号)
	when 常量2 then 要现实的值2或语句2;
	...
	else 要显示的值n或语句n;
	end
*/

/*案例:查询员工的工资,要求
	部门号=30,显示的工资为1.1倍
	部门号=40,显示的工资为1.2倍
	部门号=50,显示的工资为1.3倍
	其他部门,显示的工资为原工资
*/

SELECT `salary` AS 工资,
		`department_id`,
		CASE `department_id`
		WHEN 30 THEN `salary`*2#这里是值所以不需要分号
		WHEN 40 THEN `salary`*3
		WHEN 50 THEN `salary`*4
		ELSE salary
		END AS 新工资
FROM `employees`;



#case的使用二:类似于多重if
/*
	java中:
		if(条件1){
			语句1;
		}else if(条件2){
			语句2;
		}
		...
		else{
			语句n;
		}
		
	MYSQL中:
		case
		when 条件1 then 要显示的值1或语句1(注意值不加分号,因为没有结束,语句要加,告诉该语句已经结束
		when 条件2 then 要显示的值2或语句2
		...
		else 要显示的值
		end
	与上面方法1相比,case后面没有字段
*/


/*
	案例:查询员工的工资情况
		如果工资>20000,显示A级别
		如果工资>15000,显示B级别
				>10000,显示C级别
		否则,显示D级别
*/

SELECT 	salary,
		`employee_id`,
		CASE
		WHEN salary>20000 THEN 'A'  #一定要注意,这样写case对应的是列表中的一个字段
		WHEN salary>15000 THEN 'B'	#所以要以,分隔
		WHEN salary>10000 THEN 'C'
		ELSE 'D'
		END AS 工资级别
FROM `employees`;



============================================================================================================================================================================================================================

17_52单行函数案例解析

#1.显示系统时间(注:日期+时间)
SELECT NOW();#2021-09-26 21:00:27


#2.查询员工号,姓名,工资,以及工资提高百分之20%后的结果(new salary)
SELECT `employee_id`,`last_name`,`salary`,salary*1.2 AS `new salary`
FROM `employees`;

#3.将员工的姓名按首字母排序(只按首字母排序),并写出姓名的长度(LENGTH)
SELECT `last_name`,SUBSTR(`last_name`,1,1) AS 首字母,LENGTH(`last_name`)
FROM `employees`
ORDER BY 首字母;#这里如果写`last_name`她会按照首字母,第二个字母,第三个字母,依次排序




#4.做一个查询,产生下面的结果
#<last_name> earns <salary> monthly but wants <salary*3>Dream salary
#king earns 24000 monthly but wants 72000

SELECT CONCAT(`last_name`,' earns',`salary`,' monthly but wants',`salary`) AS hh
FROM `employees`;


#5.使用cASE一WHEN,按照下面的条件:
#job				grade
#AD_PRES			A
#sT_MAN				B
#IT_PROG			C
#sA_REP   			D
#sT_CLERK			E
#产生下面的结果
#Last_name		Job_id		Grade
#k_ing			AD_PRES		  A



SELECT `last_name`,
		`job_id` AS job,
		CASE `job_id`
		WHEN 'AD_PRES' THEN 'A'
		WHEN 'sT_MAN' THEN 'B'
		WHEN 'IT_PROG' THEN 'C'
		WHEN 'sA_REPS' THEN 'D'
		WHEN 'sT_CLERK' THEN 'E'
		END AS Greate
FROM `employees`
WHERE `job_id`='AD_PRES';

============================================================================================================================================================================================================================

18_53分组函数的介绍

#分组函数
/*
	功能:用作统计使用,又称为聚合函数或统计函数或组函数
	分类:
		sum:求和
		avg:平均值
		max:最大值
		min:最小值
		count:统计个数
	特点:
		1.sum,avg一般用于处理数值型
		  max,min,count可以处理任何类型
		  
		  
		2.以上分组函数都是否忽略null
		
		
		3.以上分组函数可以和distinct搭配实现去重的运算
			
		4.count的单独介绍
			一般使用count(*)统计行数
		5.和分组函数一同查询的字段要求是group by后的字段
*/

#1.简单的使用
SELECT SUM(`salary`)FROM `employees`;#691400.00
SELECT AVG(`salary`)FROM `employees`;#6461.682243
SELECT MAX(`salary`)FROM `employees`;#24000.00
SELECT MIN(`salary`)FROM `employees`;#2100.00
SELECT COUNT(`salary`);#107,统计行数FROM `employees`;

SELECT SUM(`salary`),AVG(`salary`),MAX(`salary`),MIN(`salary`),
		COUNT(`salary`)
FROM `employees`;


SELECT ROUND(AVG(`salary`),2)#6461.68
FROM `employees`;



#2.参数支持那些类型
SELECT SUM(`last_name`),AVG(`last_name`)
FROM `employees`;#0,0 没有实际意义

SELECT MAX(last_name),MIN(last_name)
FROM `employees`;#Zlotkey,Abel

SELECT MAX(`hiredate`),MIN(`hiredate`)
FROM `employees`;#2016-03-03 00:00:00,1992-04-03 00:00:00

SELECT COUNT(`commission_pct`),COUNT(`hiredate`)
FROM `employees`;#35 107,统计不为null的行(null即为空)


#3.忽略null
SELECT SUM(`commission_pct`),AVG(`commission_pct`),
		SUM(`commission_pct`)/35,
		SUM(`commission_pct`)/107
FROM `employees`;


SELECT MAX(`commission_pct`),MIN(`commission_pct`)
FROM `employees`;


#4.和distinct搭配
SELECT SUM(DISTINCT `salary`),SUM(`salary`)
FROM `employees`;#397900.00.691400.00

SELECT COUNT(DISTINCT `salary`)#计算有几种工资
FROM `employees`;#57


#5.count函数的详细介绍
SELECT COUNT(`salary`)
FROM `employees`;#107

SELECT COUNT(*)#这里是一行里面只要有一个不为空就记录
FROM `employees`;#107

SELECT COUNT(1)#好像添加一列,里面全是1,统计1的个数
FROM `employees`;



#效率
#myisam存储引擎下,count(*)效率高
#innodb存储引擎下,count(*)和count(1)效率差不多,比count(字段)效率高



#6.和分组函数一同查询的字段有限制
SELECT AVG(salary),hiredate#6461.682243,1992-04-03 00:00:00
FROM employees;#不报错,但没有什么意义为了保持表的工整型

============================================================================================================================================================================================================================

19_58分组函数案列详解

#1.查询公司员工工资的最大值,最小值,平均值,总和Ⅰ
SELECT MAX(`salary`),MIN(`salary`),AVG(`salary`),SUM(`salary`)
FROM `employees`;


#2.查询员工表中的最大入职时间和最小入职时间的相差天数(DIFFRENCE)
SELECT DATEDIFF(MAX(`hiredate`),MIN(`hiredate`)) AS DIFFRENCE
FROM `employees`;#8735


#3.查询部门编号为90的员工个数
SELECT COUNT(*)
FROM `employees`
WHERE `department_id`=90;

============================================================================================================================================================================================================================

20_59分组查询

#进阶5:分组查询
#引入:查询"每个部门"的平均工资
#可以使用group by子句语法
/*
	语法:
		select 分组函数,列(要求出现在group by后面)
		from 表
		where 筛选条件
		group by 分组的列表
		order by 子句
	注意:
		查询列表必须特殊,要求是分组函数和group by后出现的字段
	
	特点:
		1.分组查询的筛选条件分为两类:
								数据源				位置					关键字
			分组前筛选  		原始表				group by子句的前面		where
			分组后筛选			分组后的结果集		group by子句的后面		having
			
		分组函数做条件肯定是放在having子句中
			原始表中肯定没有分组后的数据,你又需要用这个数据做判断
			那肯定是分组后的结果表中查找了
		group by子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有分组要求)
			表达式或函数(用得较少)
		可以添加排序,放在最后(这是毫无疑问的,对于结果排序)
*/


#案例1:查询每个工种的最高工资
	#查询salary,并统计最大值 查询job_id
	#分组依据是job_id,即统计每个工种的
	#最大工资
SELECT MAX(salary),job_id
FROM `employees`
GROUP BY `job_id`;



#案例2:查询每个位置上的部门个数
SELECT COUNT(*),`location_id`
FROM `departments`
GROUP BY `location_id`;


#添加筛选条件
#案例1:查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(`salary`),`department_id`
FROM `employees`
WHERE `email` LIKE '%a%'
GROUP BY `department_id`;


#案例2:查询有奖金的每个领导手下员工的最高工资
	#查询每个领导,所以是以领导作为分组依据
SELECT MAX(salary),`manager_id`
FROM `employees`
WHERE NOT ISNULL(`commission_pct` )
GROUP BY `manager_id`;




#添加复杂的筛选条件
#案例1:查询那个部门的员工个数>2
	#1.查询每个部门的员工个数
	#2.根据1的结果查询那个部门的员工个数大于2
SELECT COUNT(*) AS 统计,`department_id`
FROM `employees`
GROUP BY `department_id`
HAVING 统计>2;#这里给的是新表的列名,这里是在上面得到的表中统计大于二的

#案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资

SELECT MAX(salary) AS 最高工资,`job_id`
FROM `employees`
WHERE NOT ISNULL(`commission_pct`)
GROUP BY `job_id`#以job_id进行分组.得到每一个工种的最大值,是一个表
#在得到的新表里面查找
HAVING 最高工资>12000;




#案例3:查询领导编号>102的每个领导手下最低工资大于5000的领导编号是那个,以及最低工资
SELECT MIN(salary) AS 最低工资,`manager_id`
FROM `employees`
WHERE `manager_id`>102
GROUP BY manager_id
HAVING 最低工资>5000;



#按表达式和函数分组
#案例1:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数大于5的有那些

SELECT COUNT(*) AS 员工数
FROM `employees`
GROUP BY LENGTH(`last_name`)
HAVING 员工数>5;  #好像group by和having后面放别名不是很通用,orcle就不支持


#按多个字段分组
#案例:查询每个部门,每个工种的员工的平均工资
SELECT AVG(salary),department_id,job_id
FROM `employees`
GROUP BY `department_id`,`job_id`;#假如说有一部门id为1,工种为"工程师"
#那么就是算又是部门id为1,又是工程师的所有人,组成的平均工资


#添加排序
#案例:查询每个部门,每个工种的员工的平均工资,并且按工资从高到低排序
SELECT AVG(salary),`department_id`,`job_id`
FROM `employees`
GROUP BY `department_id`,`job_id`#具有相同department_id和job_id的一组
ORDER BY AVG(salary) DESC;


#案例:查询每个部门,每个工种的员工的平均工资,并且按工资从高到低排序
#去掉没有部门的,平均工资小于等于10000的
SELECT AVG(salary),`department_id`,`job_id`
FROM `employees`
WHERE NOT ISNULL(`department_id`)
GROUP BY `department_id`,`job_id`#具有相同department_id和job_id的一组
HAVING AVG(salary)>10000
ORDER BY AVG(salary) DESC;


============================================================================================================================================================================================================================

21_68分组查询案例详解

#1.查询各job_id的员工工资的最天值,最小值,平均值,总和,并按job_id升序
SELECT MAX(`salary`),MIN(`salary`),AVG(`salary`),
		SUM(`salary`),`job_id`
FROM `employees`
GROUP BY `job_id`
ORDER BY `job_id`;


#2.查询员工最高工资和最低工资的差距(DIFFERENCE)
SELECT MAX(`salary`)-MIN(`salary`) AS DIFFERENCE
FROM `employees`;

#3.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的
	#员工不计算在内
	
SELECT MIN(`salary`),`manager_id`
FROM `employees`
WHERE NOT ISNULL(`manager_id`)
GROUP BY `manager_id`
HAVING MIN(`salary`)>6000;



#4.查询所有部门的编号,员工数量和工资平均值,并按平均工资降序
SELECT `department_id`,COUNT(*),AVG(`salary`)
FROM `employees`
GROUP BY `department_id`
ORDER BY AVG(`salary`) DESC;

#5.选择各个job id具有的员工人数 
SELECT COUNT(*),job_id
FROM `employees`
GROUP BY job_id;

============================================================================================================================================================================================================================

22_69连接查询,笛卡尔积介绍

#连接查询
/*
	含义:又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
	笛卡尔乘积现象:表1有m行,表2有n行,结果=m*n行
		发生原因:没有有效的连接条件
		如何避免:添加有效的连接条件
	
	分类:
		按年代分类:
			sql92标准:仅仅支持内连接
			sql99标准[推荐]:支持内连接+外连接(左外和右外)+交叉连接
		按功能分类:
			内分类:
				等值连接
				非等值连接
				自连接
			外分类:
				左外连接
				右外连接
				全外连接
			交叉分类
*/

SELECT * FROM `beauty`;
SELECT * FROM `boys`;

SELECT `name`,`boyName`
FROM `beauty`,`boys`; #这排列组合导致男女朋友太多了哈哈哈

SELECT `name`,`boyName`
FROM `beauty`,`boys`
WHERE beauty.`boyfriend_id`=boys.`id`;

============================================================================================================================================================================================================================

23_71等值连接介绍

#一:sql92标准
#1.等值连接
/*
	1.多表等值连接为多表的交集部分
	2.n表连接至少需要n-1个连接条件
	3.多表的顺序没有要求
	4.一般需要为表起别名
	5.可以搭配前面介绍的所有子句使用,比如排序,分组,筛选
	 
*/
#案例1:查询女神名和对应的男神名
SELECT `name`,`boyName`
FROM `beauty`,`boys`
WHERE beauty.`boyfriend_id`=boys.`id`;
#拿表1第一行和表2中4行进行比较,对于满足where条件的可输出
#再拿表1第2行.......
#第三行..
#...

#案例2:查询员工名和对应的部门名
SELECT `last_name`,`department_name`
FROM `employees`,`departments`
WHERE `employees`.`department_id`=`departments`.`department_id`;


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


#3.两个表的顺序是否可以交换-->可以
#查询员工名,工种号,工种名
SELECT e.`job_id`,`last_name`,`job_title`
FROM `jobs` AS j,`employees` AS e
WHERE e.`job_id`=j.`job_id`;


#4.可以加筛选
#案例:查询有奖金的员工名,及其对应的部门名
SELECT `last_name`,`department_name`,`commission_pct`
FROM `departments` AS d,`employees` AS e
WHERE d.`department_id`=e.`department_id` AND NOT ISNULL(`commission_pct`);


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



#5.可以加分组
#案例1:查询每个城市的部门个数
SELECT COUNT(*),`city`#
FROM `locations` l,`departments` d#相当于合并成两个表,这种合并是两个一个列匹配多个行
WHERE l.`location_id`=d.`location_id`#每一个部门都有对应的id,匹配成功说明是一致的
#相当于把获得的冗余的表筛选一下
GROUP BY `city`;#通过城市分组


			
#案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
	#奖金在`employees`中有,
	#每个部门需要进行分组
SELECT `department_name`,d.`manager_id`,MIN(salary)
FROM `employees` e,`departments` d
WHERE e.`department_id`=d.`department_id` AND NOT ISNULL(`commission_pct`)
#确定当前员工所属部门
GROUP BY d.`department_id`;



#6.可以加排序
#案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
		#每个工种,以工种进行分类 ,员工个数是分组函数
		
SELECT `job_title`,COUNT(*)#统计分组员工个数
FROM `jobs` j,`employees` e#这是合并两张表,存在冗余
WHERE e.`job_id`=j.`job_id`#确定该员工是那个工种
GROUP BY j.`job_id`#通过工种分类
ORDER BY COUNT(*) DESC;



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


============================================================================================================================================================================================================================

24_7374非等值连接和自连接

#非等值连接
#案例1:查询员工的工资和工资级别
SELECT `salary`,`grade_level`
FROM `employees` e,`job_grades` j#存在冗余
WHERE e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`
AND `grade_level`='A';

SELECT `employee_id`,`salary` FROM `employees`;

#自连接
#自己和自己连接
#案例:查询员工名和上级的名称
	#首先查一遍员工表,获得上级编号
	#在查一遍员工表,找到上级编号对应的是那个员工
SELECT e.`last_name`,m.`last_name`
FROM `employees` e,`employees` m
WHERE e.`manager_id`=m.`employee_id`;

============================================================================================================================================================================================================================

25_75测试题2

#一、显示员工表的最大工资,工资平均值
SELECT MAX(`salary`),AVG(`salary`)
FROM `employees`;


#二、查询员工表的employee_id,job_id, last_name ,按department_id降序,salary升序
SELECT `employee_id`,`job_id`,`last_name`,d.`department_id`,e.`salary`
FROM `employees` e,`departments` d
ORDER BY d.`department_id` DESC,e.`salary`; 


#三、查询员工表的job_id中包含a和e的,并且a在e的前面
SELECT `job_id`
FROM `employees`
WHERE `job_id` LIKE '%a%e%';
#四、已知表student,里面有id(学号),name,gradeId(年级编号)
	#已知表grade,里面有id(年级编号),name(年级名)
	#己知表result,里面有id,score,studentNo(学号)
#要求查询姓名,年纪名,成绩
SELECT s.name,g.name,r.score
FROM student s,grade g,result r
WHERE s.gtadeId=g.id AND s.id=r.studentNo;
	
#五、显示当前日期,以及去前后空格,截取子字符串的函数
SELECT NOW(),TRIM(" "),SUBSTR()









============================================================================================================================================================================================================================

26_77作业详解

#1.显示所有员工的姓名,部门号和都门名称
SELECT `last_name`,e.`department_id`,`department_name`
FROM `employees` e,`departments` d#存在冗余进行筛选
WHERE e.`department_id`=d.`department_id`;

#2.查询90号部门员工的job_id和90号部门的location_id
SELECT `job_id`,`location_id`
FROM `employees` e,`departments` d
WHERE e.`department_id`=d.`department_id`#确定该员工对应部门
AND e.`department_id`=90;#确定是否为90号部门



#3.选择所有有奖金的员工的last_name,department_name,location_id,city
SELECT `last_name`,`department_name`,d.`location_id`,`city`#这里涉及了三张表
FROM `employees` e,`departments` d,`locations` l#存在冗余,需要进行筛选
WHERE e.`department_id`=d.`department_id`
AND d.`location_id`=l.`location_id`
AND NOT ISNULL(e.`commission_pct`);


#4.选择city在Toronto工作的员工的last_name , job_id , department_id , department_name
SELECT `last_name`,`job_id`,d.`department_id`,`department_name`,`city`
FROM `employees` e,`departments` d,`locations` l#存在冗余,进行筛选
WHERE l.`city`='Toronto'
AND e.`department_id`=d.`department_id`#确定员工是这个部门的
AND d.`location_id`=l.`location_id`;#确定部门是这个城市的




#5.查询每个工种、每个部门的部门名、工种名和最低工资
SELECT `department_name`,`job_title`,MIN(salary)
FROM `departments` d,`jobs` j,`employees` e
WHERE e.`job_id`=j.`job_id`#确定该员工是那个工种
AND e.`department_id`=d.`department_id`#确定该员工是那个部门
GROUP BY j.`job_id`,d.`department_id`;#以部门和工种分类

#6.查询每个国家下的部门个数大于2的国家编号
SELECT `country_id`,COUNT(*) 部门个数#查询国家编号
FROM `locations` l,`departments` d#存在冗余,进行筛选
WHERE d.`location_id`=l.`location_id`#确定这个部门在这个国家
GROUP BY l.`country_id`#以国家进行分组
HAVING 部门个数>2;


#7.选择指定员工的姓名,员工号,以及他的管理者的姓名和员工号,结果类似于下面的格式
#employees		Emp 	#manager Mgr#
#kochhar 101    king    100

SELECT e.`last_name`,e.`employee_id`,m.`last_name`,m.`employee_id`
FROM `employees` e,`employees` m#这玩意是个自连接
WHERE e.`manager_id`=m.`employee_id`;



============================================================================================================================================================================================================================

27_79sql99语法-等值连接

#sql99语法


/*
	语法:
		select 查询列表
		from 表1 别名 连接类型
		join 表2 别名 
		on 连接条件
		where 筛选条件
		group by 分组
		having 筛选条件
		order by排序列表
		
		
	分类:
		内连接:
			inner
		外连接
			左外:
				left
			右外:
				right
			全外:
				full
		交叉连接:
			cross
*/

/*
	1.内连接
		语法:
			select 查询列表
			from 表1 别名
			inner join 表2 别名
			on 连接条件
		分类:
			等值连接
			非等值连接
			自连接
		特点:
			--添加排序,分组和筛选
			--inner可以省略
			--筛选条件放在where后面,连接条件放在on后面,提高分离性,便以阅读
*/



	#等值连接
#案例1.查询员工名,部门名
SELECT `last_name`,`department_name`
FROM `employees` e
INNER JOIN `departments` d
ON e.`department_id`=d.`department_id`;


#案例2:查询名字中包含e的员工名和工种名(添加筛选)
SELECT `last_name`,`job_title`
FROM `employees` e
INNER JOIN `jobs` j
ON e.`job_id`=j.`job_id`
WHERE e.`last_name` LIKE '%e%';



#案例3:查询部门个数>3的城市名和部门个数(分组+筛选)
SELECT `city`,COUNT(*)
FROM `departments` d
INNER JOIN `locations` l
ON d.`location_id`=l.`location_id`#确定这个部门在这个位置
GROUP BY l.`city`#对新获得的表进行分组
HAVING COUNT(*)>3;#已经分组了,相当于是一个新表 



#案例4:查询那个部门的员工个数>3的部门名和员工个数,并按个数降序(添加排序)
SELECT `department_name`,COUNT(*) 员工个数
FROM `departments` d
INNER JOIN `employees` e
ON e.`department_id`=d.`department_id`#确定这个员工是在这个部门,将e和d合成一张大表
GROUP BY d.`department_id`
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;


#案例5:查询员工名,部门名,工种名,并按部门名降序
SELECT `last_name`,`department_name`,`job_title`
FROM `employees` e
INNER JOIN `departments` d ON e.`department_id`=d.`department_id`
INNER JOIN `jobs` j ON e.`job_id`=j.`job_id`
ORDER BY `department_name` DESC;




============================================================================================================================================================================================================================

28_sql99语法-非等值连接

#非等值连接
#查询员工的工资级别
SELECT `salary`,`grade_level`
FROM `employees` e
INNER JOIN `job_grades` j
ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`;



#查询每个工资级别的个数,并且按工资级别降序
SELECT `grade_level`,COUNT(*) 工资级别个数
FROM `employees` e
INNER JOIN `job_grades` j
ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`
GROUP BY j.`grade_level`
HAVING COUNT(*)>20
ORDER BY COUNT(*) DESC;

============================================================================================================================================================================================================================

29_sql99语法-自连接

#自连接
#查询员工的名字,和其对应上级的名字
SELECT e.`last_name`,m.`last_name`
FROM `employees` e
INNER JOIN `employees` m
ON e.`manager_id`=m.`employee_id`;



#查询名字中包含字符k的员工的名字,和其对应上级的名字
SELECT e.`last_name`,m.`last_name`
FROM `employees` e
INNER JOIN `employees` m
ON e.`manager_id`=m.`employee_id`
WHERE e.`last_name` LIKE '%k%';

============================================================================================================================================================================================================================

30_82左(右)外连接

/*
	外连接
		应用场景:
			用于查询一个表中有,另一个表没有的记录
		特点:
			1.外连接的查询结果为主表中的所有记录
				如果从表中有和他匹配的,则显示匹配的值
				如果从表中没有和他匹配的,则显示null
				可以认为:
					外连接查询结果=内连接查询结果+主表中有但从表中没有的记录
			2.左外连接,left join左边的是主表
			  右外连接,right join右边的是主表 
			3.全外连接=内连接结果+表1有表2没有+表2有表1没有
*/

#引入,查询男朋友,不在男神表的女神名
SELECT `name`,`boyName`#查询女神名
FROM `beauty` t
LEFT JOIN `boys` b
ON t.`boyfriend_id`=b.`id`;

#上面可以把主表(女神)中男朋友在男神表,或者不在都输出
#左外连接
SELECT `name`,`boyName`#查询女神名
FROM `beauty` t
LEFT JOIN `boys` b
ON t.`boyfriend_id`=b.`id`
WHERE ISNULL(`boyName`); 


#右外连接
SELECT `name`,`boyName`#查询女神名
FROM `boys` b
RIGHT JOIN `beauty` t
ON t.`boyfriend_id`=b.`id`
WHERE ISNULL(`boyName`); 


#以男神表为主表
SELECT `name`,`boyName`#查询女神名
FROM `boys` b
LEFT JOIN `beauty` t
ON t.`boyfriend_id`=b.`id`p;



#查询那个部门没有员工
SELECT e.`employee_id`,d.*
FROM `departments` d
LEFT JOIN `employees` e
ON e.`department_id`=d.`department_id`#确定这个员工是这个部门
WHERE e.`employee_id` IS NULL;#因为部门表为主表,会和员工表所有行匹配一遍
#只要有一个员工在这个部门里面,那么就不会存在null的情况
#只有一个都没匹配上,才会出现null



#全外
#不支持


#交叉连接
SELECT b.*,bo.*
FROM beauty b
CROSS JOIN boys bo;#交叉连接就是笛卡尔乘积,默认的效果

============================================================================================================================================================================================================================

31_86案例详解

#一.查询编号>3的女神的男朋友信息,如果有则列出详细,如果没有,用null填充
SELECT *
FROM `beauty` be
LEFT JOIN `boys` b
ON be.`boyfriend_id`=b.`id`
WHERE be.id>3;


#二.查询那个城市没有部门
SELECT *
FROM `locations` l
LEFT JOIN `departments` d
ON d.`location_id`=l.`location_id`#确定部门在这里
WHERE ISNULL(`department_id`);


#三.查询部门名为SAL,或IT的员工信息
SELECT d.`department_name`,e.* #存在名字相同的部门(不是同一部门)
FROM `departments` d
LEFT JOIN `employees` e
ON d.`department_id`=e.`department_id`
WHERE d.`department_name`='SAL'
OR d.`department_name`='IT'

============================================================================================================================================================================================================================

32_88where后面的标量子查询

#子查询
/*
	含义:
		出现在""其他语句""中的select语句,称子查询或内查询
		外部的查询语句,称为主查询或外查询
	
	分类:
	
		按子查询出现的位置:
			select后面:
				仅仅支持标量子查询
			from后面:
				支持表子查询
			where或having后面:
				标量子查询
				列子查询
				
				行子查询(用到较少)
			exists后面(相关子查询)
				表子查询
			
			
		按结果集的行列式分类:
			标量子查询(结果集只有一行,一列)
			列子查询(结果集有一列多行)
			行子查询(结果集有一行多列)
			表子查询(结果集一般为多行多列)
*/



#一.where和having后面
/*
	标量子查询(单行子查询)
	列子查询(多行子查询)
	行子查询(多列多行)
	特点:
		--子查询放在小括号内
		--子查询一般放在条件的右侧
		--单行子查询,一般搭配着单行操作符使用
			>,<,>=,<=,=,<>
		--列子查询,一般搭配着多行操作符使用
			in,any/some,all
*/


#1.标量子查询(单行子查询)

#案例1:谁的工资比Abel高?
#①查询Abel的工资
SELECT salary
FROM `employees`
WHERE `last_name`='Abel';

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





#案例2:返回job_id与141号员工相同,salary比143号员工多的员工信息
SELECT *
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 *
FROM `employees`
WHERE salary=(
	SELECT MIN(salary)
	FROM `employees`);




#案例4:查询最低工资大于50号部门最低工资的部门id和其最低工资

#50号部门最低工资
SELECT MIN(salary)
FROM `employees` e
GROUP BY e.`department_id`
HAVING e.`department_id`=50;


SELECT MIN(salary)
FROM `employees`
GROUP BY `department_id`
HAVING MIN(salary)>(
	SELECT MIN(salary)
	FROM `employees` e
	GROUP BY e.`department_id`
	HAVING e.`department_id`=50);



#非法使用标量子查询
	#结果为多行
	#结果为空









============================================================================================================================================================================================================================

33_90where后面的行子查询

#列子查询(多行子查询)
/*
	where和having后面,充当条件
	返回多行
	需要搭配"多行比较符'使用
	
	in/not in 			等于列表中的任意一个
	any/some			和子查询返回的某一个值比较
	all					和子查询返回的所有值比较
*/


#案例1:返回location_id是1400或1700的部门中的所有员工的姓名

#一:查询出位置是1400和1700的部门
SELECT `department_id`,`location_id`
FROM `departments`
WHERE `location_id` IN (1400,1700);


SELECT `last_name`
FROM `employees` e
WHERE `department_id` IN (
	SELECT `department_id`
	FROM `departments`
	WHERE `location_id` IN (1400,1700));
	
	
	
#案例2:返回其他部门中比job_id为'IT_PROG'部门任一工资低的员工的:工号,姓名,job_id
#以及salary

#一返回job_id中所有员工的工资
SELECT DISTINCT salary
FROM `employees`
WHERE `job_id`='IT_PROG';


SELECT `employee_id`,`last_name`,`job_id`,`salary`
FROM `employees`
WHERE salary<ANY(SELECT DISTINCT salary
			FROM `employees`
			WHERE `job_id`='IT_PROG')
AND job_id!='IT_PROG';



#案例3:返回其他部门中比job_id为'IT_PROG'部门任一工资低的员工的:工号,姓名,job_id
#以及salary
SELECT `employee_id`,`last_name`,`job_id`,`salary`
FROM `employees`
WHERE salary<ALL(SELECT DISTINCT salary
			FROM `employees`
			WHERE `job_id`='IT_PROG')
AND job_id!='IT_PROG';




#行子查询(结果集一行多列或多行多列),只适用于等于情况
#案例:查询员工编号最小并且工资最高的员工信息
SELECT *
FROM `employees`
WHERE (salary,`employee_id`)=(
	SELECT MAX(salary),MIN(`employee_id`)
	FROM `employees`);

#最小员工编号
SELECT MIN(`employee_id`)
FROM `employees`;

#最高工资
SELECT MAX(salary)
FROM employees;

#查找
SELECT *
FROM `employees`
WHERE `employee_id`=(
			SELECT MIN(`employee_id`)
			FROM `employees`)
AND `salary`=(
			SELECT MAX(salary)
			FROM employees
);


#二.select后面,仅仅支持标量子查询
#案例:查询每个部门的所有信息以及对应的员工个数
#如果使用count(*)会导致为空的记录不出来
#应该为员工个数为0
SELECT COUNT(*)
FROM `employees` e,`departments` d
WHERE e.`department_id`=d.`department_id`;

SELECT d.*,(
	SELECT COUNT(*)
	FROM `employees` e
	WHERE e.`department_id`=d.`department_id`)
FROM `departments` d;



#案例2:查询员工号=102的部门名

SELECT `department_id`
FROM `employees`
WHERE `employee_id`=102;
	
	
SELECT (
	SELECT `department_name`
	FROM `employees` e
	INNER JOIN `departments` d
	ON e.`department_id`=d.`department_id`
	WHERE `employee_id`=102
);




============================================================================================================================================================================================================================

猜你喜欢

转载自blog.csdn.net/qq_53183608/article/details/120327798