您的位置:首页 > 博客中心 > 数据库 >

MySQL

时间:2022-03-16 12:03

MySQL

一,为什么要学习数据库

数据库的好处

  1. 持久化数据到本地
  2. 可以实现结构化查询,方便管理

二,数据库相关的概念

DBMS

  • 数据库管理系统(Database Management System)。数据库是通过DBMS创建和操作的容器。

DB

  • 数据库(database):存储数据的“仓库”。保存了一系列有组织的数据。

SQL

  • 结构化查询语言(Structure Query Language):专门用来于数据库通信的语言。

SQL的优点

  1. 不是某个特定的数据库供应商专有的语言,几乎所有的DBMS都支持SQL
  2. 简单易学
  3. 虽然简单,但是实际上是一种强有力的语言,灵活使用其语言元素,可以进行非常复杂和高级的数据库操作。

三, 数据库存储数据的特点

  1. 将数据放到表中,表再放到库中
  2. 一个数据库中可以有多个表,每个表都有一个名字,用来表示自己。表名具有唯一性
  3. 表具有一些特性,这些特性定义了数据库在表中如何存储,类似Java中"类"的设计
  4. 表有列组成,我们也成为字段。所有表都是由一个或多个列组成,每一列类似Java中的"属性"
  5. 表中的数据是按行存储的,每一行类似于Java中的"对象"

四, 初始mysql

MySQL产品的介绍

  • MySQL数据隶属于MySQL AB公司,总部位于瑞典
  • 08年被sun公司收购
  • 09年sun被Oracle收购

优点:

  • 成本低:开放源代码,一般可以免费使用
  • 性能高:执行很快
  • 简单:很容易和使用

DBMS分为两类

  • 基于共享文件系统的DBMS(Access)
  • 基于客户机-服务器的DBMS(MySQL Oracle SqlServlet)

MySQL的目录结构

  1. bin目录:用于放置一些可执行的文件。
  2. data目录:用于放置一些日志文件以及数据库。
  3. include目录:用于放置一些头文件。
  4. ilb目录:用于放置一系列的库文件。
  5. share目录:用于存放字符集语言等信息。
  6. my.ini:是MySQL数据库中使用的配置文件。
  7. my-huge.ini:适合超大型数据库的配置文件。
  8. my-large.ini:适合大型数据库的配置文件。
  9. my-medium.ini:适合中小型数据库的配置文件。
  10. my-small.ini:适合小型数据库的配置文件。
  11. my-template.ini:是配置文件的模板,MySQL配置向导将配置文件中选择项写入到my.ini文件中。
  12. my-innodb-heavy-4G.ini:表示配置文件只对于InnoDB存储引擎有效,而且服务器的内存不能小于4G。
  • 需要注意的是,在上述的7个配置文件中,my.ini是MySQL正在使用的配置文件,改文件是一定会被读取的,其他配置文件都是适合不同的数据库配置文件的模板,会在某些特殊情况下被读取的,如果没有特殊需求,只需要配置my.ini文件即可。

MySQL产品的安装

  • 属于c/s架构的软件,一般来讲安装服务端
  • 企业版
  • 社区版

MySQL服务的启动和停止

  1. 通过命令行
    • net start mysql
    • net stop mysql
  2. 方式二:计算机 -- 右击 -- 管理 -- 服务

MySQL服务的登陆和退出

  • 登陆:

    1. 通过MySQL自带的客户端

      只限于root用户

    2. 通过Windows自带的客户端

      myslq [-h主机名 -p端口号] -u用户名 -p密码

      mysql -h localhost -P 3306 -u root(用户名) -p(密码)

  • 退出:

    exit 或者 CTRL + C

MySQL常见的命令

查看数据库的版本

  1. 在myslq客户端:select version();
  2. 在Windows命令提示符中输入:mysql --version

显示都有那些数据库:show databases ;

使用某个数据库:use 指定的库名;

查看表:show tables; / show tables from 库名称;

查看当前在那个库:select database();

创建表:create table 表名 (id int, name varchar(20));

查看表结构:desc 表名; describe的缩写

查看数据库的编码字符集:show create database 数据库名称;

查看表所有的列:show full columns from 表名;

查看表数据:select * from 表名;

插入行数据:insert into 表名 (列名1,列名2,...) value(值1,值2,...);

修改列操作:update 表名 set 列名=‘值‘ where id = ? ;

删除列:delete from 表名 where id=?;

MySQL的语法规范

  1. 不区分大小写,但建议关键字大写,表名,列名小写

  2. 每条命令最好用分号结尾

  3. 每条命令根据需要,可以进行缩进 或者换行

  4. 注释

    单行注释:#注释文字

    单行注释:-- 注释文字

    多行注释:/* 注释文字 */

五, DQL语言的学习(Data Query Language)

基础查询

  • 语法

    select 查询列表 from 表名;
    

    类似于:System.out.println(打印东西);

  • 特点

    1. 查询列表可以是:表中的字段,常量值,表达式,函数,也可以是多个
    2. 查询的结果是一个虚拟的表格
  • 查询时注意的细节

    1. 先去打开指定的库。
    2. `` 着重号:键盘1旁边的,去掉也是没事的。用来区分是否是一个关键字的。
    3. 执行的时候选中要执行的命令即可。格式化也是一样的。

1. 查询表中的单个字段

  • 格式:select 字段名 from 表名;
SELECT last_name FROM employees;

2. 查询表中的多个字段

  • 格式:select 字段名,字段名 from 表名;

  • 查询多个使用逗号隔开(英文)最后一个不用添加逗号

SELECT last_name,salary,email FROM employees;

3. 查询表中的所有字段

  • 格式:select * from 表名;
SELECT 
  employee_id,
  first_name,
  last_name,
  email,
  phone_number,
  job_id,
  salary,
  commission_pct,
  manager_id,
  department_id,
  hiredate 
FROM
  employees ;
# * 代表所有字段
SELECT * FROM employees;

4. 查询常量值

  • 格式:select 常量值;
  • 注意:字符型和日期型的常量必须用单引号引起来,数值型不需要
SELECT 100; #100
SELECT ‘john‘;#john 

5. 查询表达式

  • 可以使用加,减,乘,除,取余,取模
  • 不可以使用加加,减减
SELECT 100%98; #2

6. 查绚函数

  • 格式:select 函数(实参列表);
#version() 查看MySQL的版本号
SELECT VERSION();

7. 起别名

注意事项:

  1. 便于理解。
  2. 如果要查询的字段有重名的情况,使用起别名可以区分开来
  3. 如果别名有特殊符号:空格,#号,等等。建议把别名加上双引号/单引号

格式:

  • select 查询的字段 as 结果;
# 方式一:使用 as
SELECT 100%98 AS 结果;
SELECT last_name AS 姓,first_name AS 名 FROM employees;
# 方式二:使用空格
SELECT last_name 姓,first_name 名 FROM employees;
#案例:查询salary,显示结果位 out put
SELECT	salary AS ‘out put‘ FROM employees;

8. 去重:

  • 在字段名的前面加上一个关键字 distinct
  • 格式:select distinct 字段名 from 表名;
#案例:查询员工表中涉及到的所有的部门编号
SELECT DISTINCT department_id FROM employees ;

9. +号的作用:

作用(回忆):

  1. 运算符,两个操作数都为数值型
  2. 连接符,只要有一个操作数为字符串
MySQL中的+号
仅仅只有一个功能:运算符
select  100+90; 两个操作数都为数值型,则做加法运算
select ‘123‘+90;只要其中一方为字符型,试图将字符型数值转换成数值型。
					如果转换成功,则继续做加法运算
select ‘john‘+90;	如果转换失败,则将字符型值转换成0

select null+10;只要其中一方为null,则结果肯定为null

10. 使用concat函数实现连接

  • 功能:拼接字符

  • 案例:查询员工名和性连接成一个字段,并显示位姓名 使用:concat(str,str,...)函数

#select last_name+first_name as 姓名 from employees; #错误?的
SELECT  CONCAT(last_name,first_name ) AS 姓名 FROM employees;

11. ifnull函数

  • 功能:判断某子字段或表达式是否为null,如果为null,返回指定的值,否则返回原来的值
select ifnull (commission_pct,0) from employees;

12.isnull函数

  • 功能:判断某字段或表达式是否为null,如果是,则返回1,否则返回0.
SELECT ISNULL(commission_pct),commission_pct FROM employees;

条件查询

  • 语法:

    select 
    	查询列表
    from
    	表名
    where
    	筛选条件;
    #先执行表名,筛选条件,查询列表。
    
  • 分类:

    1. 简单条件运算符

      条件运算符:> < = !=或<> >= <=

    2. 按逻辑表达式筛选

      逻辑运算符:&& || !

      ? and or not

      作用:用于连接条件表达式

      &&或and:两个条件都为true,结果为true,反之为false

      ||或or:只要有一个条件为true,结果为true,反之为false

      !或not:如果连接的条件本身为false,结果为true,反之为false

    3. 模糊查询

      • like

        特点

        1. 一般和统配符搭配使用,可以判断字符型或数值型

          通配符:

          % :任意多个字符,包含0个字符

          _ :任意单个字符

      • between and

        注意

        1. 使用 **between and **可以提高语句的简洁度
        2. 包含临界值
        3. 两个临界值不要调换顺序
      • in

        含义:判断某字段的值是否属于in列表中的某一项

        特点

        1. 使用in提高语句简洁度
        2. in列表的值类型必须一致或兼容
        3. in括号里面的值不可以使用通配符(因为是等于不是like)
      • is null / is not null

        注意

        1. =或<>不能用于判断null值
        2. is null或is not null 可以判断null值
      • <=> 安全等于

      is null V/S <=>

      IS NULL:仅仅可以判断NULL值,可读性较高,建议使用
      <=> :既可以判断NULL值,又可以判断普通的数值,可读性较低

一,按条件运算符筛选

  • 案例1:查询工资>1200的员工信息

    SELECT * FROM employees WHERE salary>12000;
    
  • 案例2:查询部门编号不等于90号的员工名和部门编号

    SELECT CONCAT(last_name,first_name),department_id 
    FROM employees 
    WHERE department_id <>90;
    

二,按逻辑表达式筛选

  • 案例1:查询工资在1w到2w之间的员工名,工资以及奖金

    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; 
    WHERE department_id <90 OR department_id>110 OR salary	>=15000; 
    

三,模糊查询

1. like
  • 案例1:查询员工名中包含字符a的员工信息

    SELECT * FROM employees 
    WHERE last_name LIKE ‘%a%‘;
    
  • 案例2:查询员工名中第三个字符为n,第五个字符为l的员工名和工资

    SELECT last_name,salary FROM employees 
    WHERE last_name LIKE ‘__n_l%‘
    
  • 案例3:查询员工名中第二个字符为_的员工名(使用转义字符或使用escape关键字)

    SELECT last_name FROM employees 
    WHERE last_name LIKE ‘_$_%‘ ESCAPE ‘$‘;
    #where last_name like ‘_\_%‘;
    
2. between and
  • 案例1:查询员工编号在100到120之间的员工信息

    SELECT * FROM employees 
    #where employee_id >=100 and employee_id<=120;
    WHERE employee_id BETWEEN 100 AND 120; 
    
3. in
  • 案例1:查询员工的工种编号是 IT_PROG AD_VP AD_preS 中的一个员工名和工种编号

    SELECT last_name,job_id FROM employees 
    #where job_id =‘IT_PROG‘ or job_id =‘AD_VP‘ OR job_id =‘AD_preS‘;
    WHERE job_id IN(‘IT_PROG‘,‘AD_VP‘,‘AD_preS‘);
    
4. is null / is not null
  • 案例1:查询没有奖金的员工名和奖金率

    SELECT last_name,commission_pct FROM employees 
    WHERE commission_pct IS NULL;# 不可以使用=(等号)因为它不可以判断null值   
    #------------------以下为错误?
    SELECT last_name,commission_pct FROM employees 
    WHERE commission_pct IS 12000;
    
5.安全等于:<=>
  • 案例1:查询没有奖金的员工名和奖金率

    SELECT last_name,commission_pct FROM employees 
    WHERE commission_pct <=> NULL;
    
  • 案例2:查询工资为12000的员工信息

    SELECT last_name,salary FROM employees 
    WHERE salary <=> 12000;
    

排序查询

  • 引入:

    SELECT * FROM employees;
    
  • 语法

    select 查询列表
    from 表
    【where 筛选条件】
    order by 排序列表 【asc|desc】;
    
  • 特点

    1. asc代表的是升序,desc代表的是降序如果不写,默认是升序.
    2. order by子句中可以支持单个字段,多个字段,表达式,函数,别名.
    3. order by子句一般是放在查询语句的最后面,limit子句除外.
  • 执行顺序from表,where筛选条件,select查询列表,order by 排序条件

案例:

  1. 案例1:查询员工信息,要求工资从高到底排序

    SELECT * FROM employees ORDER BY salary DESC;
    
  2. 案例2:查询部门编号>=90的员工信息,按入职时间的先后进行排序【添加筛选条件】

    SELECT * FROM employees
    WHERE department_id >=90
    ORDER BY hiredate ASC;
    
  3. 案例3:按年薪的高低显示员工的信息和年薪【按表达式排序】

    SELECT *,salary*12*(1+IFNULL(commission_pct,0)) ‘年薪‘ FROM employees 
    ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;
    
  4. 案例4:按年薪的高低显示员工的信息和年薪【按别名排序】

    SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees 
    ORDER BY 年薪 DESC;
    
  5. 案例5:按姓名的长度显示员工的姓名和工资【按函数排序】

    SELECT LENGTH(last_name) 字节长度,last_name,salary
    FROM employees ORDER BY LENGTH(last_name) DESC;
    
  6. 案例6:查询员工信息,要求先按工资升序,再按员工编号降序【按多个字段排序】

    SELECT * FROM employees
    ORDER BY salary ASC ,employee_id DESC;
    

常见的函数

类似于Java的方法,将一组逻辑语句封装在方法中,对外暴露方法名

  • 好处:1. 隐藏了实现细节 2. 提高代码的重用性

  • 调用:select 函数名(实参列表) 【from 表】;

  • 特点:

    1. 叫什么(函数名)
    2. 干什么(函数功能)
  • 分类:

    1. 单行函数

      如:concat,length,ifnull等

    2. 分组函数

      功能:做统计使用,又称为统计函数,聚合函数,组函数

  • 常见函数:

    • 字符函数:
      length concat substr instr trim upper lower lpad rpad replace
    • 数学函数:
      round ceil floor truncate mod rand
    • 日期函数
      now curdate curtime year month monthname day hour minute second str_to_date date_faormat datediff monthname
    • 其他函数:
      version database user
    • 控制函数
      if case

一,字符函数

  1. length 获取参数值的字节个数

    SELECT LENGTH(‘john‘);#4
    SELECT LENGTH(‘呵呵呵‘);#9 (utf-8中文占3个字节)
    # 查看客户端使用的字符集
    SHOW VARIABLES LIKE ‘%char%‘;
    
  2. concat 拼接字符串

    SELECT CONCAT(last_name,‘_‘,first_name) 姓名 FROM employees;
    
  3. upper,lower 变大写边小写

    SELECT UPPER(‘jhon‘);#JHON
    SELECT LOWER(‘jHon‘);#jhon
    #实例:将姓变大写,名变小写,然后拼接
    SELECT CONCAT(UPPER( last_name),LOWER (first_name)) 姓名 FROM employees;
    
  4. substr,substring

    注意:索引从1开始

    #截取从指定索引处后面所有字符
    SELECT SUBSTR(‘李莫愁爱上了陆展元‘,7); out_put;#陆展元
    
    #截取从指定索引处指定字符长度的字符
    SELECT SUBSTR(‘李莫愁爱上了陆展元‘,1,3); out_put;#李莫愁
    
    #案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
    SELECT CONCAT( UPPER( SUBSTR(last_name,1,1)),‘_‘,LOWER(SUBSTR(last_name,2)) )
    FROM employees;
    
  5. **instr **返回子串第一次出现的索引,如果找不到返回0

    SELECT INSTR(‘杨不悔爱上了殷六侠‘,‘殷六侠‘) AS out_put;#7
    
  6. **trim **前后去重

    SELECT LENGTH(TRIM(‘   张翠山   ‘)) out_put;#9
    SELECT TRIM(‘a‘ FROM ‘aaaaaaa张aa翠aa山aaaaa‘) out_put ;#张aa翠aa山
    
  7. lpad 使用指定的字符实现左填充指定长度

    SELECT LPAD(‘殷素素‘,10,"*") AS out_put;#*******殷素素
    SELECT LPAD(‘殷素素‘,2,"*") AS out_put;#殷素
    
  8. **rpad **使用指定的字符实现右填充指定长度

    SELECT RPAD(‘殷素素‘,12,"ab") AS out_put;#殷素素ababababa
    SELECT RPAD(‘殷素素‘,2,"ab") AS out_put;#殷素
    
  9. replace 替换

    SELECT REPLACE(‘张无忌爱上了周驰若‘,‘周驰若‘,‘赵敏‘) out_put;#张无忌爱上了赵敏
    SELECT REPLACE(‘周驰若爱上了周驰若‘,‘周驰若‘,‘赵敏‘) out_put;#赵敏爱上了赵敏
    

二,数学函数

  1. **round **四舍五入

    SELECT ROUND(2.5);#3
    SELECT ROUND(-1.4);#-1
    SELECT ROUND(-1.5);#-2
    SELECT ROUND(1.5767,2);#1.58  
    
  2. ceil 向上取整,返回>=该参数的最小整数

    SELECT CEIL(1.0001);#2
    SELECT CEIL(-1.02);#-1
    
  3. **floor **向下取整,返回<=该参数的最大整数

    SELECT FLOOR(9.99);#9
    SELECT FLOOR(-9.99);#10  
    
  4. **truncate **截断

    SELECT TRUNCATE(1.6999,1);#1,6   
    
  5. **mod **取余

    mod(a,b) : a-a/b*b

    mod(10,-3) : -10-(-10)/(-3)*(-3)=-1

    SELECT MOD(10,3);#1
    SELECT MOD(-10,3);#-1
    
  6. rand:获取随机数,返回0-1之间的小数

三.1,日期函数

  1. now 返回当前系统日期+时间

    SELECT NOW();
    
  2. curdate 返回当前系统日期,不包含时间

    SELECT CURDATE();
    
  3. curtime 返回当前时间,不包含日期

    SELECT CURTIME();
    
  4. 可以获取指定的部分,年,月,日,小时,分钟,秒

    SELECT YEAR(NOW()) 年;
    SELECT YEAR(‘2020-12-1‘) 年;
    #查询入职时间
    SELECT YEAR (hiredate) FROM employees;
    
    #查询月份中文
    SELECT MONTH(NOW()) 月;
    #查询月份英文
    SELECT MONTHNAME(NOW()) 月;
    #日day,小时hour,分钟minute ,秒second 
    
  5. datediff两个日期之差

    SELECT DATEDIFF(NOW(),‘2000-11-08‘);	
    SELECT DATEDIFF(‘2020-1-3‘,‘2020-1-10‘);#-7 
    

三.2,字符日期转换函数

  • str_to_date:将日期格式的字符转换成指定格式的日期

    SELECT STR_TO_DATE(‘9-13-1999‘,‘%m-%d-%y‘);#1999-09-13
    
    #查询入职如期 日期为1992-4-3的员工信息
    SELECT * FROM employees WHERE hiredate =‘1992-4-3‘;
    SELECT * FROM employees WHERE hiredate=STR_TO_DATE(‘4-3 1992‘,‘%c-%d %Y‘);
    
  • date_format:将日期转换成字符

    SELECT DATE_FORMAT(‘2018/6/6‘,‘%Y年%m月%d日‘);#2018年06月06日
    SELECT DATE_FORMAT(NOW(),‘%Y年%m月%d日‘);
    #查询有奖金的员工名和入职日期(xx月/xx日 xxxx年)
    SELECT last_name,DATE_FORMAT( hiredate,‘%m月/%d日 %Y年‘) 入职日期,commission_pct
    FROM employees WHERE commission_pct IS NOT NULL;
    
  • 技术图片

四,其他函数

SELECT VERSION();#查看当前MySQL的版本
SELECT DATABASE();# 查看当前数据库
SELECT USER();# 查看当前用户
select md5(‘字符‘)#返回该字符的md5的密码形式
select password(‘字符‘);#返回该字符的密码形式

五,流程控制函数

  1. if函数 ??*if else **的效果

    格式:if(条件表达式,表达式成立返回的值,条件表达式不成立返回的值)

    SELECT IF(10>5,‘大‘,‘小‘);#大
    SELECT last_name,commission_pct,IF(commission_pct IS NOT NULL,‘有奖金‘,‘没奖金‘) FROM employees ;
    
  2. case函数的使用一:switch case 的效果

    • java中:

      switch(变量或表达式){
      	case 常量1:语句1;break;
      	...
      	default:语句n;break;
      }
      
    • MySQL中:

      case 要判断的字段或表达式
      when 常量1 then 要显示的值1或语句1;
      when 常量2 then 要显示的值1或语句2;
      ...
      else 要显示的值n或语句n;
      end
      
    • 案例:查询员工的工资,要求
      部门号=30,显示的工资为1.1倍
      部门号=40,显示的工资为1.2倍
      部门号=50,显示的工资为1.3倍
      其他部门,显示的工资为原工资

      SELECT department_id,salary 原始工资,
      CASE department_id
      WHEN 30 THEN salary*1.1
      WHEN 40 THEN salary*1.2
      WHEN 50 THEN salary*1.3
      ELSE salary 
      END 新工资 FROM employees
      ORDER  BY department_id;
      
  3. 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 要显示的值n或语句n
      end
      
    • 案例:查询员工的工资的情况
      如果工资>20000,显示A级别
      如果工资>15000,显示B级别
      如果工资>10000,显示C级别
      否则,显示D级别

      SELECT employee_id,salary,
      CASE 
      WHEN salary>20000 THEN ‘A‘
      WHEN salary>15000 THEN ‘B‘
      WHEN salary>10000 THEN ‘C‘
      ELSE ‘D‘
      END 级别 FROM employees
      ORDER BY salary DESC;
      

分组函数

  • 功能:用作统计使用,又称为聚合函数或统计函数或组函数

  • 分类:sum求和,avg平均值,max最大值,min最小值,count计算个数

  • 特点:

    1. sumavg一般用于处理数值型

    2. 以上分组函数忽略null值

    3. 可以和distinct特配实现去重的运算

    4. count函数的单独介绍

      一般使用count(*)做统计行数

    5. 和分组函数一同查询的字段要求是 group by 后的字段

  1. 简单的使用

    SELECT SUM(salary) FROM employees;
    SELECT AVG(salary) FROM employees;
    SELECT MAX(salary) FROM employees;
    SELECT MIN(salary) FROM employees;
    SELECT COUNT(salary) FROM employees;
    
    SELECT SUM(salary) 和,AVG(salary) 平均,MAX(salary) 最大,MIN(salary) 最小,COUNT(salary) 个数 
    FROM employees;
    SELECT SUM(salary) 和,ROUND(AVG(salary),2)平均,MAX(salary) 最大,MIN(salary) 最小,COUNT(salary) 个数 
    FROM employees;#平均值保留两位小数
    
  2. 参数支持那些类型

    SELECT SUM(last_name),AVG(last_name) FROM employees;#不支持
    SELECT SUM(hiredate), AVG(hiredate) FROM employees;#不支持
    # sum avg 一般用于处理数值型 
    
    SELECT MAX(last_name),MIN(last_name) FROM employees;
    SELECT MAX(hiredate),MIN(hiredate) FROM employees;
    # max min 支持字符和日期型
    
    SELECT COUNT(commission_pct) FROM employees; 
    SELECT COUNT(last_name) FROM employees;
    # count 只支持不为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;
    SELECT COUNT(commission_pct) FROM employees;
    SELECT commission_pct FROM employees; 
    
  4. distinct搭配

    SELECT SUM(DISTINCT salary),SUM(salary) FROM employees;
    SELECT COUNT(DISTINCT salary),COUNT(salary) FROM employees;  
    
  5. **count **函数的详细介绍

    SELECT COUNT(salary) FROM employees;
    SELECT COUNT(*)FROM employees;#统计行数
    SELECT COUNT(1)FROM employees;#统计行数
    效率:
    MYISAM 存储引擎下,COUNT(*) 的效率高
    INNODB 存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
    
  6. 和分组函数数一同查询的字段有限制

    SELECT AVG(salary),employee_idl FROM employees;#意义不大
    

分组查询

  • 语法:

    	select 分组函数,列(要求出现在group by的后面)  ⑤
    	from 表  ①
    	【where 筛选条件】  ②
    	group by 分组的列表  ③
    	【having 分组后的筛选】  ④
    	【order by 子句】  ⑥
    

    执行顺序:from,where,group by,having,select,order by

  • 注意:

    查询列表必须特殊,要求是分组函数和group by后出现的字段

  • 特点:

    1. 分组查绚中的筛选条件分为两类

      数据源 位置 关键字
      分组前筛选 原始表 group by子句的前面 where
      分组后筛选 分组后的结果集 group by子句的后面 having

      分组函数做条件肯定是放在having子句中

      能用分组前筛选的,优先考虑使用分组前筛选

    2. group by 子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有顺序要求),表达式或函数(用的较少)

    3. 也可以添加排序(排序放在整个分组查询的最后)

引入

#查询每个部门的平均工资
SELECT department_id,AVG(salary) FROM employees 
GROUP BY department_id ORDER BY department_id;

#案例1,查询每个工种的最高工资
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 commission_pct IS NOT NULL
GROUP BY employee_id;

添加分组后的筛选条件

#1. 查询每个部门的员工个数
SELECT COUNT(*) a,department_id
FROM employees
GROUP BY department_id;
#2. 根据1的结果进行筛选,查询那个部门的员工个数>2
SELECT COUNT(*) a,department_id
FROM employees
GROUP BY department_id
HAVING a>2;

#案例2:查询每个工种有奖金的员工的做高工资>12000的工种编号和最高工资
#1. 查询每个工种有奖金的员工的最高工资
#2. 根据1结果继续筛选,最高工资>12000
SELECT job_id,MAX(salary) a
FROM employees
WHERE commission_pct IS NOT NULL 
GROUP BY job_id
HAVING a>12000;

#案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号是哪个,以及其最低工资
#1. 查询每个领导手下的员工固定最低工资
#2. 添加筛选条件:编号>102
#3. 添加筛选条件:最低工资>5000
SELECT MIN(salary) a,manager_id 
FROM employees
WHERE manager_id>102
GROUP BY manager_id
HAVING a>5000;

按表达式或函数分组

#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
#1. 查询每个长度的员工个数
#2. 添加筛选条件
SELECT  COUNT(*) a,LENGTH(last_name) b
FROM employees
GROUP BY b
HAVING a>5;

按多个字段分组

#案例:查询每个部门每个工种的员工的平均工资
SELECT AVG(salary),department_id,job_id
FROM employees
GROUP BY department_id,job_id;

添加排序

#案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示
SELECT AVG(salary) a,department_id,job_id
FROM employees
GROUP BY department_id,job_id
HAVING a>10000
ORDER BY a DESC;

练习

USE myemployees;
#1. 查询各job_id的员工工资的最大值,最小值,平均值,总和,并按job_id升序
SELECT job_id,MAX(salary),MIN(salary),ROUND( AVG(salary),2),SUM(salary)
FROM employees 
GROUP BY job_id 
ORDER BY job_id ASC;
#2. 查询员工最高工资和最低工资的差距
SELECT MAX(salary)-MIN(salary)
FROM employees ;
#3. 查询各个管理者手下员工的最低工资,其中最低工资不能小于6000,没有管理者的员工不计算在内
SELECT MIN(salary) s
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_id
HAVING s>=6000;
#4. 查询所有部门的编号,员工数量和工资平均值,并按平均工资降序
SELECT department_id,COUNT(*),AVG(salary) a
FROM employees
GROUP BY department_id
ORDER BY  a DESC;
#5. 选择具有各个job_id的员工人数
SELECT COUNT(*),job_id FROM employees GROUP BY job_id;

连接查询

一,含义

  • 当查询中设计到了多个表的字段,需要使用多表连接
  • 格式:select 字段1,字段2 from 表1,表2,...;
  • 笛卡尔乘积:当查询多个表时,没有添加有效的连接条件,导致多个表所有行实现完全连接
  • 如何解决:添加有效的来连接条件

二,分类

按年代分类

  • sql192

    等值

    非等值

    自连接

    也支持一部分外连接(用于Oracle,SQL server,MySQL不支持)

  • sql99【推荐使用】

    内连接

    1. 等值
    2. 非等值
    3. 自连接

    外连接

    1. 左外
    2. 右外
    3. 全外(mysql不支持)

    交叉连接

按功能分类

  • 内连接

    等值连接,非等值连接,自连接

  • 外连接:

    左外连接,右外连接,全外连接

  • 交叉连接:

三,sql92语法

  1. 等值连接

    • 语法:

      select 查询列表
      from 表2 别名,表2 别名
      where 表1.key=表2.key
      【and 筛选条件】
      【group by 分组字段】
      【having 分组后的筛选】
      【order by 排序字段】
      
    • 特点:

      1. 多表等值连接的结果为多表的交集部分
      2. n表连接,至少需要n-1个连接条件
      3. 多表的顺序没有要求
      4. 一般需要为表起别名
      5. 可以搭配前面介绍的所有子句使用,比如排序,分组,筛选
  2. 非等值连接

    • 语法:

      select 查询列表
      from 表2 别名,表2 别名
      where 表1.key=表2.key
      【and 筛选条件】
      【group by 分组字段】
      【having 分组后的筛选】
      【order by 排序字段】
      
  3. 自连接

    • 语法:

      select 查询列表
      from 表2 别名,表2 别名
      where 表1.key=表2.key
      【and 筛选条件】
      【group by 分组字段】
      【having 分组后的筛选】
      【order by 排序字段】
      

四,sql99语法

语法:

	select 查询列表
	from 表1 别名 
	【连接类型】
	join 表2 别名
	on 连接条件
	【where 筛选条件】
	【group by 分组】
	【having 筛选条件】
	【order by 排序列表】

分类:

  • 内连接(?):inner
  • 外连接
    1. 左外(?):left 【outer】
    2. 右外(?):right 【outer】
    3. 全外:
  • 交叉连接:

特点,语法:

  1. 内连接

    语法:

    select 查询列表
    from 表1 别名
    inner join 表2 别名
    on 连接条件
    

    分类:等值,非等值,自连接

    特点:

    1. 添加排序,分组,筛选
    2. **inner **可以省略
    3. 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
    4. inner join连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集
    5. 表的顺序可以调换
  2. 外连接

    语法:

    select 查询列表
    from 表1 别名
    left|right|full outer join 表2 别名
    on 连接条件
    

    应用场景:用于查询一个表中有,另一个表没有的记录

    特点:

    1. 外连接的查询结果为主表中的所有记录
      如果从表中有和它匹配的,则显示匹配的值
      如果从表中没有和它匹配的,则显示null
      外连接查询结果=内连接查询结果+主表中有而从表没有的记录
    2. 左外连接,left join 左边的是主表
      右外连接,
      right join
      右边的是主表
    3. 左外和右外交换两个表的顺序,可以实现同样的效果
    4. 全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的
    5. outer可以省略
  3. 交叉连接

    语法:

    select 查询列表
    from 表1 别名
    cross join 表2 别名
    

    特点:使用99语法实现笛卡尔乘积

sql99 和 sql99区别:

  • 功能:sql99支持的较多
  • 可读性:slq99实现连接条件和筛选条件的分离,可读性

代码实例:

USE girls;
SELECT	* FROM beauty;
SELECT * FROM boys;
SELECT NAME,boyName FROM boys,beauty;#这种现象称之为笛卡尔积现象

SELECT NAME,boyName FROM boys,beauty
WHERE boys.id=beauty.boyfriend_id;#连接条件

sql92标准

  1. 等值连接

    1. 简单的等值连接

      #案例1:查询女神名对应的男神名
       SELECT *,boys.`boyName`
       FROM beauty,boys
       WHERE beauty.boyfriend_id=boys.id;
       #案例2:查询员工名对应的部门名
       USE myemployees;
       SELECT last_name,department_name
       FROM employees,departments
       WHERE employees.`department_id`=departments.`department_id`;
      
    2. 为表起别名

      • 提高语句的简洁度

      • 区分多个重名的字段

      注意:如果为表起了别名,则查询的字段就不能使用原来的表名区限定

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

      #查询员工名,工种号,工种名
      SELECT last_name,e.job_id,job_title
      FROM jobs j,employees e
      WHERE j.job_id= e.job_id;
      
    4. 可以加筛选

      #案例:查询有奖金的员工名,部门名
      SELECT last_name,department_name
      FROM employees e,departments d
      WHERE e.`department_id`=d.`department_id` AND commission_pct IS NOT NULL;
      #案例2:查询城市中第二个字符为o的部门名和城市名
      SELECT department_name,city	
      FROM departments d,locations l
      WHERE d.`location_id`=l.`location_id` AND l.`city` LIKE ‘_o%‘;
      
    5. 可以加分组

      #案例1:查询每个城市的部门个数
      SELECT COUNT(*),city
      FROM  departments d,locations l
      WHERE d.`location_id`=l.`location_id`
      GROUP BY city;
      #案例2:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
      SELECT department_name,d.`manager_id`,MIN(salary)
      FROM employees e,departments d
      WHERE e.`department_id`=d.`department_id` AND commission_pct IS NOT NULL 
      GROUP BY e.`department_id`;
      
    6. 可以加排序

      #案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
      SELECT job_title,COUNT(*) a  
      FROM employees e,jobs j
      WHERE e.`job_id`=j.`job_id` 
      GROUP BY e.`job_id`
      ORDER BY a DESC;
      
    7. 可以实现三表连接

      #案例:查询员工名,部门名和所在的城市
      SELECT last_name,department_name,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 salary,grade_level
    FROM employees e,job_grades g
    WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`
    AND g.`grade_level`=‘A‘;
    
    SELECT * FROM job_grades;
    
  3. 自连接

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

sql99

  1. 内连接

    • 等值连接

      USE myemployees;
      #案例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 last_name LIKE ‘%e%‘ ;
      
      #案例3,查询部门个数大于3的城市名和部门个数(分组+筛选)
      #1. 查询每个城市的部门个数
      #2. 在1结果上筛选满足条件的
      SELECT 
        city,
        COUNT(*) 
      FROM
        departments d 
        INNER JOIN locations l 
          ON d.`location_id` = l.`location_id` 
      GROUP BY city 
      HAVING COUNT(*) > 3 ;
      
      #案例4,查询那个部门的部门员工大于3的部门名和员工个数,并且按个数降序(排序)
      SELECT 
        department_name,
        COUNT(*) 
      FROM
        employees e 
        INNER JOIN departments d 
          ON e.`department_id` = d.`department_id` 
      GROUP BY department_name 
      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;
      
    • 非等值连接

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

      #查询员工的名字,上级的名字
      SELECT e.`last_name`,m.`last_name`
      FROM employees e
      JOIN employees m
      ON e.`manager_id`=m.`employee_id`
      WHERE e.`last_name` LIKE ‘%k%‘;
      
  2. 外连接

    #引入:查询没有男朋友的女神名
    USE girls;
    SELECT * FROM beauty;
    SELECT * FROM boys;
    -- 左外连接
    SELECT b.name,bo.*
    FROM  beauty b
    LEFT OUTER JOIN boys bo
    ON b.`boyfriend_id`=bo.`id`
    WHERE bo.`id` IS NULL;
    -- 右外连接
    SELECT b.`name`,a.* 
    FROM boys a
    RIGHT OUTER JOIN beauty b
    ON a.`id`=b.`boyfriend_id`
    WHERE a.`id` IS NULL;
    
    #案例1:查询那个部门没有员工
    USE myemployees;
    #左外 部门主表
    SELECT d.*,e.`employee_id`
    FROM departments d
    LEFT OUTER JOIN employees e
    ON d.`department_id`=e.`department_id`
    WHERE e.`employee_id` IS NULL;
    #右外
    SELECT d.*,e.`employee_id`
    FROM employees e
    RIGHT OUTER JOIN departments d 
    ON d.`department_id`=e.`department_id`
    WHERE e.`employee_id` IS NULL;
     
     #全外 MySQL不支持
     USE girls;
     SELECT b.*,bo.*
     FROM beauty b
     FULL OUTER JOIN boys bo
     ON b.`boyfriend_id`=bo.id;
    
  3. 交叉连接

     SELECT b.*,bo.*
     FROM beauty b
     CROSS JOIN boys bo;
    

子查询

  • 含义:

    嵌套在其他语句内部的select语句称为子查询或内查询

    外面的语句可以是insert,update,delete,select等,一般select作为外面语句较多

    外部的查询语句,称为主查询或外查询

  • 分类:

    • 按子查询出现的位置:

      1. select后面

        仅仅标量子查询

      2. from 后面

        支持表子查询

      3. wherehaving后面 ★

        标量子查询 √

        列子查询 √

        行自查询

      4. exists后面

        标量子查询

        列子查询

        行子查询

        表子查询

    • 按结果集的行列数不同:

      1. 标量子查询(结果集只有一行一列)
      2. 列子查询(结果集只有多行一列)
      3. 行子查询(结果集有多行多列)
      4. 表子查询(结果集一般为多行多列)

一,where或having后面

  • 支持的查询:

    1. 标量子查询(单行子查询)
    2. 列子查询(多行子查询)
    3. 行子查询(多列多行)
  • 特点:

    1. 子查询放在小括号内

    2. 子查询一般放在条件的右侧

    3. 标量子查询,一般搭配着单行操作符使用

      > < >= <= <>

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

      IN,ANY/SOME,ALL

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

二,select 后面

  • 仅仅支持标量子查询

三,from后面

  • 讲子查询结果充当一张表,要求必须起别名

四,exists后面

  • 最终的结果看有没有值,有true,否则false

  • 语法:
    exists(完整的查询语句)
    结果:1或0

代码实例

  • 一,where或having后面

    1. 标量子查询

      #案例1:谁的工资比Abel高?
      #1. 查询abel的工资
      SELECT salary FROM employees WHERE last_name =‘Abel‘;
      #2. 查询员工的信息,满足salary>1结果
      SELECT * fromemployees 
      WHERE salary > 
        (SELECT salary 
        FROM employees
        WHERE last_name = ‘Abel‘);
        
      #案例2:返回job_id于141号员工相同,salary比143号员工多的员工 姓名,job_id和工资
      #1. 查询141号员工的job_id
      SELECT job_id
      FROM employees 
      WHERE employee_id=143;
      #2. 查询143号员工的salary
      SELECT salary 
      FROM employees
      WHERE employee_id=143;
      #3. 查询员工 姓名,job_id和工资,要求job_id=1并且salary>2
      SELECT e.last_name,e.job_id,e.salary
      FROM employees e
      WHERE e.`job_id`=(SELECT a.job_id FROM employees a
      	WHERE a.`employee_id`=143) 
      	AND e.`salary` > (
      	SELECT b.salary FROM employees b
      	WHERE b.`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和其最低工资
      #1. 查询50号部门的最低工资
      SELECT MIN(salary)FROM employees WHERE department_id=50;
      #2. 查询每个部门的最低工资
      SELECT MIN(salary),department_id
      FROM employees
      GROUP BY department_id;
      #3. 在2基础上筛选,满足min(salary)》1
      SELECT MIN(salary),department_id
      FROM employees
      GROUP BY department_id
      HAVING MIN(salary)>(
          SELECT MIN(salary)FROM employees 
          WHERE department_id=50);
      
      #非法使用标量子查询
      #子查询的结果不是一行一列
      SELECT MIN(salary),department_id
      FROM employees
      GROUP BY department_id
      HAVING MIN(salary)>(
          SELECT salary FROM employees 
          WHERE department_id=250);
      
    2. 列子查询(多行子查询)

      #案例1,返回location_id是1400或1700的部门中的所有员工姓名
      #1. 查询location_id是1400或1700的部门编号
      SELECT department_id FROM departments
      WHERE location_id IN(1400, 1700);
      #2. 查询员工姓名,要求部门号是1列表中的某一个
      SELECT 
        last_name 
      FROM
        employees 
      WHERE department_id IN 
        (SELECT department_id 
        FROMdepartments 
        WHERE location_id IN (1400, 1700)) ;
        
      #案例2:返回其他工种中比job_id为‘IT_PROG‘工种任意一工资的员工的:工号,姓名,job_id,salary
      #1. 查询job_id为‘IT_PROG‘的工资
      SELECT DISTINCT salary FROM employees WHERE job_id=‘IT_PROG‘;
      #2. 查询员工的:工号,姓名,job_id,salary<1的任意一个
      SELECT 
        last_name,employee_id,job_id,salary 
      FROM employees 
      WHERE salary < ANY 
        (SELECT DISTINCT salary 
        FROM employees 
        WHERE job_id = ‘IT_PROG‘) 
        AND job_id <> ‘IT_PROG‘;
      #或
      SELECT 
        last_name,employee_id,job_id,salary 
      FROM employees 
      WHERE salary < 
        (SELECT DISTINCT MAX(salary) 
        FROM employees 
        WHERE job_id = ‘IT_PROG‘) 
        AND job_id <> ‘IT_PROG‘;
      
      #案例3:返回其他部门中比job_id为‘IT_PROG‘部门所有工资都低的员工的员工号,姓名,job_id以及salary
      SELECT 
        last_name,employee_id,job_id,salary 
      FROM employees 
      WHERE salary < ALL
        (SELECT DISTINCT salary 
        FROM employees 
        WHERE job_id = ‘IT_PROG‘) 
        AND job_id <> ‘IT_PROG‘;
      #或
      SELECT 
        last_name,employee_id,job_id,salary 
      FROM employees 
      WHERE salary <
        (SELECT DISTINCT MIN(salary) 
        FROM employees 
        WHERE job_id = ‘IT_PROG‘) 
        AND job_id <> ‘IT_PROG‘;
      
      #3. 行子查询(结果集一行多列或多行多列)
      #案例:查询员工编号最小并且工资最高的员工信息
      SELECT * FROM employees 
      WHERE (employee_id,salary)=(
          SELECT MIN(employee_id),MAX(salary)
      	FROM employees);
      	
      #1. 查询最小的员工编号
      #2. 查询最高工资
      #3. 查询员工信息
      SELECT * FROM employees 
      WHERE employee_id = 
        (SELECT MIN(employee_id) FROM employees) 
        AND salary = 
        (SELECT MAX(salary)  FROM employees);
      
    3. 行子查询(结果集一行多列或多行多列)

      #案例:查询员工编号最小并且工资最高的员工信息
      SELECT * FROM employees 
      WHERE (employee_id,salary)=(SELECT MIN(employee_id),MAX(salary)
      	FROM employees);
      	
      #1. 查询最小的员工编号
      #2. 查询最高工资
      #3. 查询员工信息
      SELECT * FROM employees 
      WHERE employee_id = 
        (SELECT MIN(employee_id) FROM employees) 
        AND salary = 
        (SELECT MAX(salary)  FROM employees);
      
  • 二,select 后面

    #案例1:查询每个部门的员工个数
    SELECT d.*,(
    	SELECT COUNT(*)
    	FROM employees e
    	WHERE e.department_id=d.`department_id`)
    FROM departments d;
    #案例2:查询员工工号=102的部门名
    SELECT (SELECT department_name 
    	FROM departments d
    	INNER JOIN employees e
    	ON d.department_id=e.department_id
    	WHERE e.employee_id=102) 部门名;
    
  • 三,from后面

    #案例:查询每个部门的平均工资的工资等级
    #1. 查询每个部门的平均工资
    SELECT AVG(salary),department_id
    FROM employees GROUP BY department_id;
    #2. 连接1的结果集和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;
    
  • 四,exists后面(相关子查询)

    SELECT EXISTS(SELECT employee_id FROM employees);#1
    SELECT EXISTS(SELECT employee_id FROM employees WHERE salary =30000);#0
    
    #案例1:查询有员工的部门名
    SELECT department_name
    FROM departments d 
    WHERE EXISTS (SELECT * FROM employees e
    	WHERE e.`department_id`=d.`department_id`);
    #in
    SELECT department_name
    FROM departments d 
    WHERE d.`department_id` 
    	IN (SELECT department_id 
    	FROM employees); 
    	
    #案例2:查询没有女朋友的男生信息
    #in
    SELECT bo.* FROM boys bo 
    WHERE bo.`id` NOT IN (
    	SELECT boyfriend_id 
    	FROM beauty);
    #exists
    SELECT bo.* FROM boys bo 
    WHERE NOT EXISTS (
    	SELECT boyfriend_id
    	FROM beauty
    	WHERE bo.`id`=beauty.`boyfriend_id`)
    

分页查询

  • 应用场景:当要显示的数据,一页显示不全,需要分页提交sql请求

  • 语法:

    select 查询列表			  ⑦
    from 表			  		①
    连接类型 join 表2		 ②
    on 连接条件		    	  ③
    where 筛选条件			  ④
    group by 分组字段		  ⑤
    having 分组后的筛选  	 	⑥
    order by 排序的字段		 ⑦
    limit 【offset,】size;	⑧
    
    offset要显示条目的起始索引(起始索引从0开始)
    size要显示的条目个数
    
  • 执行顺序:from,join ,on,where,group by,having,select,order,limit

  • 特点:

    1. limit语句放在查询语句的最后

    2. 公式:

      要显示的页数page,每页的条目数size

      select 查询列表 from 表 (page-1)size ,size;

    3. offset可以省略省略默认是0

代码示例

#案例1:查询前5条员工信息
SELECT * FROM employees LIMIT 0,5;
SELECT * FROM employees LIMIT 5;#offset可选
#案例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 0,10;

union联合查询

  • union联合 合并:将多条查询语句的结果合并成一个结果

  • 语法:

    查询语句1
    union
    查询语句2
    union
    。。。;
    
  • 应用场景:

    查询的结果来自于多个表,且多个表没有直接关系,但查询的信息一致

  • 特点:

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

    1. 将一条比较复杂的查询语句拆分成多条语句
    2. 适用于多个表的时候,查询的列基本是一致的

代码实例:

#引入案例:查询部门编号>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,csex FROM t_ca WHERE csex=‘男‘
UNION
SELECT t_id,tName,tGender FROM t_ula WHERE tGender=‘male‘;

查询总结

select 查询列表		⑦
from 表1 别名		①
连接类型 join 表2	②
on 连接条件			③
where 筛选条件		④
group by 分组列表	⑤
having 筛选			⑥
order by 排序列表	 ⑧
limit 起始条目索引,条目数;  ⑨

六, DML语言的学习(Data Manipulation Language)

插入语句

  • 方式一:

    • 语法:

      insert into 表名 (列名,...) values (值1,...);
      
    • 特点:

      1. 插入的值的类型要于列的类型一致或兼容

      2. 不可以为null的列必须插入值。可以为null的列如何插入值?

        方式一:将该列插入null

        方式二:讲该列省略

      3. .列的顺序可以调换

      4. 列数和值得个数必须一致

      5. 可以省略列名,默认所有列,而且列的顺序和表中的顺序一致

      6. 除了数字类型以外,其他类型一律需要使用引号(单引号或双引号)引起来

  • 方式二:

    • 语法:

      insert into 表名 set 列名=值,列名=值,...; 
      
  • 两种方式pk

    1. 方式一支持插入多行,方式二不支持

    2. 方式一支持子查询(省略INSERT),方式二不支持

      insert into beauty(id,name,phone)
      select 26,‘宋希‘,‘118‘;
      

修改语句

  1. 修改单表的记录

    • 语法:

      update 表名
      set 字段=新值,字段=新值,...
      where 筛选条件;
      
  2. 修改多表的记录

    • sql92语法:

      update 表1 别名,表2 别名
      set 列=值,...
      where 连接条件
      and 筛选条件;
      
    • sql99语法:

      update 表1 别名
      inner|left|right join 表2 别名
      on 连接条件
      set 列=值,...
      where 筛选条件;
      
  3. 代码实例:

    #1. 修改单表的记录
    #案例一:修改beauty表中性唐的女神的电话为13783454548
    update beauty set phone =‘13783454548‘
    where name like ‘唐‘;
    
    #案例2:修改boys表中id号为2的名称为张飞,魅力值10
    update boys set boyname=‘张飞‘,usercp=10
    where id=2;
    
    #2. 修改多表的记录
    #案例1:修改张无忌的女朋友手机号为114
    update boys bo
    inner join beauty b
    on bo.`id`=b.`boyfriend_id`
    set bo.`boyName`=‘张无忌‘;
    
    #案例2:修改没有男朋友的女神的男朋友的编号都为2号
    update boys bo 
    right join beauty b
    on bo.`id`=b.`boyfriend_id`
    set b.`boyfriend_id`=2
    where bo.`id` is null;
    
    select bo.*,b.* from boys bo 
    right join beauty b 
    on bo.`id`=b.`boyfriend_id`
    

删除语句

  1. delete

    • 单表的删除

      语法:

      delete from 表名 where 筛选条件 limit 条目数;
      
    • 多表的删除

本类排行

今日推荐

热门手游