• SQL语句


    内容概要

    • SQL与NOSQL语句
    • 数据库相关概念
    • 常见基本SQL语句
    • 字符编码及基本配置文件
    • 数据库存储引擎
    • 创建表的完整语法
    • MySQL字段基本数据类型
    • MySQL字段常见约束条件
    • SQL语句查询关键字
    • 多表查询的两种方式

    SQL语句

    数据库服务端也可以服务多种类型的客户端
    	客户端可以是自己开发的,也可以是Python代码编写或JAVA代码编写
    
    SQL
    	操作关系型数据库的语言
    NOSQL
    	操作非关系型数据库的语言
    # 如果我们想要跟数据库进行交互 那么就必须使用数据库指定的语言
    
    '''
    SQL有时候也代指关系型数据库
    NOSQL有时候也代指非关系型数据库
    根据具体情况指向不同
    '''
    

    数据库重要概念

    """
    强调:小白阶段为了更加方便的理解 做了以下比喻 本质其实有一点点的区别
    """
    库			就相当于是     文件夹
    表			就相当于是	  文件夹里面的文件
    记录	        就相当于是     文件夹里面的文件中的一行行数据
    
    

    基本SQL语句

    1.SQL语句必须以分号结尾
    2.SQL语句编写错误后不需要担心,执行报错即可
    
    数据库我们知道,它其实就是对数据进行增删改查操作的
    

    查看所有库的名称:

    show databases;
    image

    查看所有表名称

    show tables,因为表在库中,我们需要先进入库中才可以查看库中的表
    输入命令 use 库名;
    image

    image
    这样就显示出了所有在stundent中的表名

    查看所有记录

    select * from mysql.user;

    基于库的增删改查

    创建库

    create database 库名;
    image

    查看指定库

    show create database 库名;
    image

    编辑库

    alter database 库名 charset='utf8';
    image

    删除库

    drop database 库名
    image

    基于表的增删改查

    创建表
    操作表之前需要先确定库

    use student; 我们先进入这个student表中
    image
    查看库中所有的表
    image
    create table 表名(字段名 字段类型,字段名 字段类型);
    image

    查看表

    	show tables;  查看库下所有的表名称
    	show create table 表名;  查看指定表信息
    	describe 表名;  查看表结构
    	desc 表名;
     	ps:如果想跨库操作其他表 只需要在表名前加库名即可
        			desc mysql.user;
    

    编辑表

    alter table 表名 rename 新表名 ;
    image

    删除表

    drop table 表名字;
    image

    添加表字段

    alter table 表名 add 字段名 字段类型(数字)约束条件;

    将新添加的表字段插入到某个字段名下面

    alter table 表名 add 字段名 字段类型(数字)约束条件 after 已有字段;

    修改字段类型

    alter table 表名 modify 新字段类型(数字)约束条件;

    修改字段名字和类型

    alter table 表名 change 旧表名 新表名 字段类型(数字)约束条件;

    基于记录的增删改查

    增加数据

    insert into 表名 valuse(数据值,);
    image

    查找数据

    select 数据名字 from 表名; * 为全部
    image

    image

    修改数据

    update 表名 set 字段名=新数据 where 筛选条件;
    image

    删除数据

    delete from 表名
    image

    delete from 表明 where 选择条件
    image

    字符编码与配置文件

    当前用户、版本、编码、端口号

    \s查看MySQL相关信息
    image

    解决MySQL 5.6.44 编码不统一问题

    image

    MySQL5.6及之前的版本编码需要人为统一 之后的版本已经全部默认统一
    如果我们想要永久的去配置字符编码,那么我们就需要对MySQL的配置文件进行一些修改
    
    # 1.utf8mb4能够存储表情 功能更强大
    # 2.utf8与utf-8是有区别的 MySQL中只有utf8
    

    MySQL 5.6.44默认的配置文件名字为 my_defalut.ini 我们需要对配置文件进行复制并且重命名为my.ini
    image

    image

    my.ini配置文件内容修改如下:
    image

    [mysqld]
    
    character-set-server=utf8mb4 
    
    [client]
    
    default-character-set=utf8mb4 
    
    [mysql]
    
    default-character-set=utf8mb4
    

    保存后重启服务即可完成字符编码设置
    show variables like '%char%'
    image

    MySQL存储引擎

    存储引擎:
    	是数据库针对数据采取的多种存取方式
    查看常见存储引擎的方式:
    	show engines;
    

    image

    常见的四个存储引擎

    MyISAM
    	MySQL5.5版本之前的默认存储引擎
    	存储数据的速度比较快,但是功能比较少,安全性较低
    InnoDB
    	MySQL5.5版本之后默认的存储引擎
    	支持事物、行锁、外键、等操作 存取速度没有MyISAM快,但是安全性更高
    Memory
    	基于内存存取数据 仅用于临时表数据存取
    BlackHole
    	任何写入进去的数据都会立刻丢失
    

    我们可以创建四张表来看看在数据库文件中都是什么样子的

    image

    1.innodb两个文件
    	.frm	表结构
    	.ibd	表数据(表索引)
    2.myisam三个文件
    	.frm	表结构
    	.MYD	表数据
    	.MYI	表索引
    3.memory一个文件
    	.frm	表结构
    4.blackhole一个文件
    	.frm	表结构
    

    image
    MySQL对大小写不敏感

    创建表的完整语法

    create table 表名(
    	字段名 字段类型(数字) 约束条件,
    	字段名 字段类型(数字) 约束条件,
     	字段名 字段类型(数字) 约束条件
    );
    	1.字段名和字段类型是必须的
    	2.数字和约束条件是可选的
    	3.约束条件也可以写多个 空格隔开即可
    	4.最后一行结尾不能加逗号
    

    如图
    image
    表结构
    image

    字段类型

    字段类型之整形

    image

    tinyint			1bytes			正负号(占1bit)
    smallint		2bytes			正负号(占1bit)
    int			4bytes		        正负号(占1bit)
    bigint			8bytes			正负号(占1bit)
    
    我们也可以取消正负号
    	create table t6(id tinyint unsigned);
     	insert into t6 values(-129),(128),(1000);
    
    数字在很多地方都是用来表示限制存储数据的长度 
    	但是在整型中数字却不是用来限制存储长度
     
    create table t1(id int(3));  不是用来限制长度
    insert into t1 values(12345);
    
    create table t2(id int(5) zerofill);  而是用来控制展示的长度
    insert into t2 values(123),(123456789);
    
    create table t14(id int);
    
    """以后写整型无需添加数字"""
    
    

    严格模式

    我在表t2中插入两条数据,但是超出了字段类型的范围,没有报错!

    image

    没有报错是因为我们在之前的设置字符编码时,没有设置严格模式

    我们可以通过命令show variables liek '%mode%';来查看现在的MySQL格式
    image

    	当我们在使用数据库存储数据时,如果数据不符合我们的存储规范,应该直接报错,而不是擅自修改数据并存储进表中,这样会导致我们的数据失真(失去了存储数据的意义)
    	其实在正常情况下是应该报错的,但是我们在开头配置MySQL字符编码的时候不小心修改了配置文件
    	我们需要修改一下相应配置!
    	1.临时修改
    	set session sql_mode='strict_trans_tables';
        	在当前客户端有效
     	set global sql_mode='strict_trans_tables';
        	在当前服务端有效
    2.永久修改
    	直接修改配置文件
    

    永久修改教程

    首先我们也需要对mysql进行停止服务
    与配置字符编码的操作一样,我们只需要在my.ini的[mysqld]下面加上
    image
    sql_mode=STRICT_TRANS_TABLES 即可!
    启动服务并登录mysql就修改成功了~~
    image

    我们再次输入超出tinint范围的数字试一下:

    image

    成功报错~ 严格模式设置成功

    字段类型之浮点型

    1.float(15,10)
    	括号内数字代表,总共存储15位数 小数点后面占102.double(15,10)
    	括号内数字代表,总共存储15位数 小数点后面占103.decimal(15,10)
    	括号内数字代表,总共存储15位数 小数点后面占10

    我们新建三个表并插入小数进去,观察它们到底有什么区别
    image
    我们可以看到,float的小数 并不精确
    image
    image

    三者的核心区别在于精确度不同,
    float < double < decimal 
    

    字段类型之字符串

    char:(定长)
    	char(4) 代表的意思为,最多存储四个字符,超出就报错,如果不够四个字符会自动用空格补齐四个字符
    	
    varchar:(变长)
    	varchar(4) 代表的意思为,最多存储四个字符,超出就报错,不够则有几位就存储几位
    	
    

    image
    select char_length('字段名') from 表名;
    可以查询表中字段明的字符长度
    image

    char 与 varchar 对比
    
    char
    	优势:整存整取 速度快
    	劣势:浪费存储空间
    varchar
    	优势:节省存储空间 
    	劣势:存取数据的速度较char慢
    
    """char与varchar的使用需要结合具体应用场景"""
    
    

    字段类型之枚举与集合

    枚举
    	多选一
    	create table t15(
        	id int,
          	name varchar(32),
           gender enum('male','female','others')
        );
     	insert into t15 values(1,'tony','猛男');
      	insert into t15 values(2,'jason','male');
     	insert into t15 values(3,'kevin','others');
    
    集合
    	多选多(多选一)
    	create table t16(
        	id int,
          	name varchar(16),
           hobbies set('basketabll','football','doublecolorball')
        );
     	insert into t16 values(1,'jason','study');
     	insert into t16 values(2,'tony','doublecolorball');
    	insert into t16 values(3,'kevin','doublecolorball,football');
    

    字段类型之日期类型

    datetime		年月日时分秒
    date			年月日
    time			时分秒
    year			年
    
    create table t17(
    	id int,
      	name varchar(32),
     	register_time datetime,
     	birthday date,
     	study_time time,
     	work_time year
    );
    insert into t17 values(1,'tom','2000-11-11 11:11:11','1938-01-11','11:11:11','2000');
    ps:以后涉及到日期相关字段一般都是系统自动获取 无需我们自己操作
    

    字段约束条件

    无符号、零填充

    限制条件是我们需要在 创建表时字段名后面可以添加的
    unsigned# 无符号
    image

    无符号的限制条件为,在插入id字段数据时,不能带有负号了

    zerofill # 零填充

    	mysql -uroot -p
    	create database db1;
    	use db1;
    	create table t1(id int(4) unsigned zerofill);
    	insert into t1 values(3);
    	select * from t1;
    	+------+
    	| id   |
    	+------+
    	| 0003 |
    	+------+
    	
    

    image

    非空

    我们先来创建以一个新表t2
    create table t2 (
    	id int ,
        name varchar(32)
    );
    然后我们插入数值
    insert into t2(id) values(2);
    insert into t2 values(3,'小明');
    insert into t2(name) values('大白');
    mysql> select * from t2;
    +------+--------+
    | id   | name   |
    +------+--------+
    |    2 | NULL   |
    |    3 | 小明   |
    | NULL | 大白   |
    +------+--------+
    我们可以看到我们没有插入数值的地方 变成了NULL
    结论:所有字段类型不加约束条件的情况下都可以为空
    

    not null # 非空

    create table t3(
    	id int not null ,
    	name varchar(32)
    );
    insert into t3(name) values('小明');
    
    

    image

    默认值

    default #默认值

    默认值就时如果我们加上了默认值的约束条件,那么我们如果不给字段添加数据,字段默认值为default后面的数据,如果添加了数据就根据添加的数据来。

    create table t4(
    	id int,
    	name varchar(32) default '匿名'
    );
    insert into t4(id) values(2);
    mysql> select * from t4;
    +------+--------+
    | id   | name   |
    +------+--------+
    |    2 | 匿名   |
    +------+--------+
    insert into t4(id) values(4),(5),(6);
    mysql> select * from t4;
    +------+--------+
    | id   | name   |
    +------+--------+
    |    2 | 匿名   |
    |    4 | 匿名   |
    |    5 | 匿名   |
    |    6 | 匿名   |
    +------+--------+
    

    image

    image

    唯一值

    unique # 唯一

    单列唯一

    create table t5(
    	id int unique;
    	name varchar(32)
    );
    insert into t5 values(1,'小明'),(2,'小美');
    insert into t5 values(1,'大白');
    select * from t5;
    +------+--------+
    | id   | name   |
    +------+--------+
    |    1 | 小明   |
    |    2 | 小美   |
    +------+--------+
    

    image

    联合唯一

    unique(字段名,字段名)

    create table t7(
    	id int not null,
    	port int,
    	ip varchar(32) ,
    	unique(ip,port)
    );
    mysql> select * from t7
        -> ;
    +----+------+--------------+
    | id | port | ip           |
    +----+------+--------------+
    |  1 | 3306 | 127.0.0.1    |
    |  2 | 8080 | 127.0.0.1    |
    |  3 | 8023 | 198.168.0.11 |
    +----+------+--------------+
    
    insert into t7 values(1,'127.0.0.1',3306),(2,'127.0.0.1',8080),(3,'198.168.0.11',8023);
    
    insert into t7 values(4,'127.0.0.1',8023);
    

    image

    主键

    primary key # 主键

    主键单从约束层面上面而言主键相当于 not null + unique(唯一且非空)
    mysql> create table t8(
        -> id int primary key,
        -> name varchar(32)
        -> );
    mysql> insert into t8(name) values('小明');
    ERROR 1364 (HY000): Field 'id' doesn't have a default value
    mysql> insert into t8 values(1,'大白');
    ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
    mysql> insert into t8 values(2,'小明');
    Query OK, 1 row affected (0.00 sec)
    mysql> select * from t8;\
    +----+--------+
    | id | name   |
    +----+--------+
    |  1 | 小明   |
    |  2 | 小明   |
    +----+--------+
    
    

    image
    image

    InnoDB存储引擎规定了所有的表都必须有且只有一个主键(主键是组织数据的重要条件并且主键可以加快数据的查询速度)
    1.当表中没有主键也没有其他非空切唯一的字段的情况下
    	InnoDB会采用一个隐藏的字段作为表的主键 隐藏意味着无法使用 基于该表的数据查询只能一行行查找 速度很慢
    2.当表中没有主键但是有其他非空且唯一的字段 那么会从上往下将第一个该字段自动升级为主键
     	create table t7(
    	id int,
    	age int not null unique,
    	phone bigint not null unique,
    	birth int not null unique,
    	height int not null unique
    );
    """
    我们在创建表的时候应该有一个字段用来标识数据的唯一性 并且该字段通常情况下就是'id'(编号)字段
    	id nid sid pid gid uid
    	
    create table userinfo(
    	uid int primary key,
    );
    """
    

    自增

    auto_increment # 自增

    该约束条件不能单独出现 并且一张表中只能出现一次 主要就是配合主键一起用
    mysql> create table t9(
    	-> id int auto_increment);
    ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
    错误的表定义;只能有一个auto列,必须将其定义为键
    
    mysql> create table t9(
        -> id int primary key auto_increment);
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> create table t10(
        -> id int primary key auto_increment,
        -> name varchar(32));
    insert into t10 values('小明');
    ERROR 1136 (21S01): Column count doesn't match value count at row 1
    mysql> insert into t10(name) values('小明');
    Query OK, 1 row affected (0.00 sec)
    mysql> select * from t10;
    +----+--------+
    | id | name   |
    +----+--------+
    |  1 | 小明   |
    +----+--------+
    

    image

    外键

    外键引子

    我们需要一张员工表
    	id name age dep_name dep_desc
    1.表语义不明确(到底是员工还是部门)
    2.存取数据过于冗余
    3.数据的拓展性极差
    
    所以我们如果想要解决上述几个问题 我们需要将表 一分为2
    id name age 
    id dep_name dep_desc
    这样的话上述的三个问题就解决了
    但是问题是,这样处理后,员工与部门之间没了关系
    那么 外键的作用就是用于表示数据与数据之间关系的字段
    

    表关系

    表关系、数据关系,其实意思是一样的 知识说法上有区分
    表关系总共四种:
    	一对多
    	多对多
    	一对一
    	没有关系
    我们对关系的判断可以采用'换位思考'的原则
    

    一对多关系

    我们还是拿上述的员工与部门之间的关系为例子
    1. 先站在员工表的角度
    	问:一名员工是否可以对应多个部门?
    	答:否
    2. 再站在部门表的角度
    	问:一个部门是否能对应多个员工?
    	答:是
    那么我们就可以凭借上述问题得出结论:
    	# 一个可以一个不可以 表与表之间的关系就是一对多!
    	那么针对'一对多'关系,外键字段应该创建在'多'的一方 ,也就是 '员工'
    
    create table staff(
    	id int primary key auto_increment,
    	name varchar(32),
    	dep_id int,
    	foreign key(dep_id) references department(id)
    );
    
    create table department(
    	id int primary key auto_increment,
    	dep_name varchar(32),
    	dep_desc varchar(32)
    );
    
    1.创建表的时候一定要先创建被关联表
    2.录入表数据的时候一定要先录入被关联表
    3.修改数据的时候外键字段无法修改和删除
    针对3有简化措施>>>:级联更新级联删除
    
    create table staff1(
    id int primary key auto_increment,
    name varchar(32),
    dep_id int,
    foreign key(dep_id) references department1(id)
    on update cascade
    on delete cascade
    );
    
    create table department1(
    id int primary key auto_increment,
    dep_name varchar(32),
    dep_desc varchar(32)
    );
    
    """
    外键其实是强耦合 不符合解耦合的特性
    	所以很多时候 实际项目中当表较多的情况 我们可能不会使用外键 而是使用代码建立逻辑层面的关系
    """
    

    image

    多对多关系

    以书籍表与作者表为例
    	1.先站在书籍表的角度
    		问:一本书能否对应多个作者
    		答:可以
    	2.再站在作者表的角度
    		问:一个作者能否对应多本书
    		答:可以
    	结论:两个都可以 关系就是'多对多'
    	针对'多对多'不能在表中直接创建 需要新建第三张关系表
    
    mysql> create table author(
        -> id int primary key auto_increment,
        -> name varchar(32),
        -> phone varchar(32)
        -> );
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> create table book(
        -> id int primary key auto_increment,
        -> book_name varchar(32),
        -> book_price bigint
        -> );
    Query OK, 0 rows affected (0.02 sec)
    
    create table author2book(
    	id int primary key auto_increment,
    	author_id int,
    	foreign key(author_id) references author(id)
    	on update cascade
    	on delete cascade
    	book_id int,
    	foreign key(book_id) references book(id)
    	on update cascade
    	on delete cascade
    );
    

    image

    image

    image

    我们通过新建了一张表来做外键,这样的话 作者与书籍的关系就显现出来了!

    一对一关系

    以用户表与用户详情表为例
    	1.先站在用户表的角度
    		问:一个用户能否对应多个用户详情
    		答:不可以
    	2.再站在用户详情表的角度
    		问:一个用户详情能否对应多个用户
    		答:不可以
    	结论:两个都可以 关系就是'一对一'或者没有关系
    	针对'一对一'外键字段建在任何一方都可以 但是推荐建在查询频率较高的表中
    
    create table user(
    id int primary key auto_increment,
    name varchar(32),
    age int
    userinfo_id int unique, # 由于是一对一 所以我们需要将外键变成唯一的
    foreign key(userinfo_id) references userinfo(id)
    on update cascade
    on delete cascade
    );
    
    create table userinfo(
    id int primary key auto_increment,
    hobby varchar(32),
    titile varchar(32),
    email varchar(64)
    );
    

    SQL语句查询关键字

    select 
    	指定需要查询的字段信息-> 
    select * 
    	查询所有字段
    select score 
    	支持查询指定字段
    select char_length(score) 
    	支持对字段进行处理的查询
    from 
    	指定需要查询的表信息
        from myslq.user
        from 表名
    
    SQL语句中关键字的执行顺序宇编写顺序并不一致!
    
    select ip,port from clientinfo;
    由于我们查询的ip,port字段是属于表clientinfo的,所有他的执行顺序也是先执行 from clientinfo ,再select ip,port
    
    对应关键字的编写顺序并不需要特别刻意,再前期我们对MySQL不熟悉的情况下我们可以根据需求分步骤操作!
    

    前期数据准备

    我们提前准备一些数据,方便对下面的方法去做讲解
    
    登录mysql 然后创建一个名为db3的库
    
    create table staff_info(
    id int primary key auto_increment,
    name varchar(32) not null, # 名字非空
    gender enum('male','female') not null default'male',# 可以选male,或者female,默认值为male
    age int(3) unsigned not null default 28, # 无符号,非空,默认为28
    hire_date date not null, # 日期非空
    post varchar(64),
    post_comment varchar(128),
    salary double(15,2),
    office int,# 一个部门一个屋子
    department_id int
    );
    
    mysql> desc staff_info;
    +---------------+-----------------------+------+-----+---------+----------------+
    | Field         | Type                  | Null | Key | Default | Extra          |
    +---------------+-----------------------+------+-----+---------+----------------+
    | id            | int(11)               | NO   | PRI | NULL    | auto_increment |
    | name          | varchar(32)           | NO   |     | NULL    |                |
    | gender        | enum('male','female') | NO   |     | male    |                |
    | age           | int(3) unsigned       | NO   |     | 28      |                |
    | hire_date     | date                  | NO   |     | NULL    |                |
    | post          | varchar(64)           | YES  |     | NULL    |                |
    | post_comment  | varchar(128)          | YES  |     | NULL    |                |
    | salary        | double(15,2)          | YES  |     | NULL    |                |
    | office        | int(11)               | YES  |     | NULL    |                |
    | department_id | int(11)               | YES  |     | NULL    |                |
    +---------------+-----------------------+------+-----+---------+----------------+
    10 rows in set (0.01 sec)
    #插入记录
    #三个部门:教学,销售,运营
    insert into staff_info(name,gender,age,hire_date,post,salary,office,department_id) values
    ('sui','male',18,'20170301','浦东第一帅形象代言',7300.33,401,1), #以下是教学部
    ('tom','male',78,'20150302','teacher',1000000.31,401,1),
    ('kevin','male',81,'20130305','teacher',8300,401,1),
    ('tony','male',73,'20140701','teacher',3500,401,1),
    ('owen','male',28,'20121101','teacher',2100,401,1),
    ('jack','female',18,'20110211','teacher',9000,401,1),
    ('jenny','male',18,'19000301','teacher',30000,401,1),
    ('sank','male',48,'20101111','teacher',10000,401,1),
    ('哈哈','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
    ('呵呵','female',38,'20101101','sale',2000.35,402,2),
    ('西西','female',18,'20110312','sale',1000.37,402,2),
    ('乐乐','female',18,'20160513','sale',3000.29,402,2),
    ('拉拉','female',28,'20170127','sale',4000.33,402,2),
    ('僧龙','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
    ('程咬金','male',18,'19970312','operation',20000,403,3),
    ('程咬银','female',18,'20130311','operation',19000,403,3),
    ('程咬铜','male',18,'20150411','operation',18000,403,3),
    ('程咬铁','female',18,'20140512','operation',17000,403,3);
    

    编写SQL语句->小技巧

    针对select后面的字段名我们可以暂时先用*符号来占位置,最后回来再修改
    
    在实际应用中select后面很少直接写* 因为 * 代表全部,当表中字段与数据非常多的时候非常浪费数据库资源
    '''
    SQL语句的编写类似于代码的编写,不是一次性就能完成的,需要反复的修改,修补
    '''
    

    查询关键字 -> where筛选

    查询所有id大于等于4小于等于7的数据:

    解决方法1
    select * from staff_info where id>=4 and id<=7;
    我们可以直接在where后面指定条件,这样的话我们就可以通过select找到我们的需求
    image

    解决方法2
    select * from staff_info where id between 4 and 7; # between 在...之间
    我们也可以使用关键字between 来增加我们的筛选条件范围
    image

    查询薪资是20000或者18000或者17000的数据:

    解决方法1
    select * from staff_info where salary=17000 or salary=20000 or salary=18000;
    这种方法虽然繁琐,但是逻辑比较清晰
    image
    解决方法2
    select * from staff_info where salary in(17000,18000,20000);支持成员运算
    image

    查询id小于3大于6的数据

    解决方法1
    select * from staff_info where not id between 3 and 6;
    因为SQL支持逻辑运算符,所以我们可以通过not来做一个取反操作
    image
    解决方法2
    select * from staff_info where id<3 or id>6;
    image

    查询员工姓名中包含字母o的员工姓名与薪资

    条件不够精确的查询称之为 -> 模糊查询
    模糊查询:
      # 模糊查询的关键字为: like
      # 模糊查询的常用符号:
    			%:匹配任意个数的任意字符
    			-:匹配单个个数的任意字符
    

    解决方法1
    select name,salary from staff_info where name like '%o%';
    image

    查询员工姓名是由四个字符组成的员工姓名与其薪资

    解决方法1
    select name,salary from staff_info where name like '____';
    image

    解决方法2
    select name,salary from staff_info where char_length(name)=4;
    image

    查询岗位描述为空的员工名与岗位名 针对null不能用等号,只能用is

    解决方法
    因为null是关键字而不是字符,所以不能通过=号进行筛选比较
    select name,post_comment from staff_info where post_comment is NULL;

    """
    在MySQL中也有很多内置方法 我们可以通过查看帮助手册学习
    	help 方法名
    """
    

    image

    查询关键字 -> group by分组

    分组就是将一个个单独的数据,组成到一起,变成一个整体
    	# 将人类 按照性别 进行分组
    	# 将人类 按照肤色 进行分组
    	# 将人类 按照地域 进行分组
    分组的目的是为了更方便,更好的去统计相关的数据
    	# 人类男女性别占比
    	# 人类种族肤色占比
    	# 人类活动地域占比
    

    聚合函数

    	专门用于'分组之后'的数据统计
    	max\min\sum\avg\count
    	最大值、最小值、求和、平均值、计数
    

    将员工按照部门分组

    select * from staff_info group by post;
    """
    MySQL5.6默认不会报错
    	set global sql_mode='strict_trans_tables,only_full_group_by'
    	或者直接修改my.ini文件 将my.ini文件的sql_mode改为:sql_mode='strict_trans_tables,only_full_group_by'
    MySQL5.7及8.0默认都会直接报错
    	原因是分组之后 select后面默认只能直接填写分组的依据 不能再写其他字段
    		select post from emp group by post;
    		select age from emp group by age;		
    	分组之后默认的最小单位就应该是组 而不应该再是组内的单个数据单个字段
    """
    

    解决方法
    select post from staff_info group by post;
    image

    获取每个部门的最高工资

    我们注意题目,分组不一定是必要的,有的时候有更简单的解决方法
    要不要分组我们完全可以从题目的需求中分析出来尤其是出现关键字 每个 平均'
    

    解决方法1
    select post,max(salary) from staff_info group by post;
    image
    针对sql语句执行之后的结果 我们是可以修改字段名称的 关键字as 也可以省略
    select post as '部门',max(salary) as '最高薪资' from staff_info group by post;
    image

    注意,as 后面的字符 只在本次select 结果显示时生效,下次查询如果没有 as 命名的话还是原来的字段名!

    一次性获取部门薪资(最高薪,最低薪,平均薪资,月支出)相关统计

    解决方法
    select post,max(salary) '最高薪',min(salary) '最低薪',avg(salary) '平均薪资',sum(salary) '月支出' from emp group by post;
    image

    统计每个部门的人数

    解决方法
    select post,count(id) as 部门人数 from staff_info group by post;
    image

    我们不能直接去count(name) 是因为 name 里面可能会有重复的信息! 但是每个表的id作为主键是非空且唯一的

    统计每个部门的部门名称以及部门下的员工姓名

    select post,name from staff_info group by post;
    分组以外的字段无法直接填写 需要借助于方法 group_concat(字段名)
    image

    image

    我们也可以直接在group_concat(name,age) 这样填写,这样就会将名字与age拼起来
    image
    在group_concat()中就类似于python的字符串+字符串,也可以自己增加字符串拼接
    image

    解决方法
    select post,group_concat(name) from staff_info group by post;
    image

    查询关键字 -> having过滤

    having与where 本质是一样的 都是用来对数据进行筛选的
    但是 where 关键字是用于 分组之前 而 having 关键字是用于分组之后
    

    统计各部门年龄在30岁以上的员工平均工资,并且保留大于10000的数据

    解决方法
    select post,avg(salary) from staff_info where age>30 group by post having avg(salary) > 10000;

    image

    查询关键字 -> distinct去重

    去重有一个必须的条件也是很容易被忽略的条件
    	# 数据必须一模一样才可以去重
    

    image

    select distinct age,name,post from staff_info;
    image

    因为 distinct关键字 去重的关键字针对的是多个字段组合的结果,所以当他们组合起来一样的话就失去了单个字段的去重效果

    查询关键字 -> order by排序

    select age from staff_info order by age; # 默认升序 asc(可以省略)
    image
    select age from staff_info order by age desc 修改为降序
    image

    select * from staff_info order by age,salary desc;
    image

    这样写的话就相当于先排年龄的'升序',然后再根据工资的'降序'来排序
    

    统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资进行排序(升序)

    我们可以一步一步做,不需要一次性写完。
    1.先筛选出所有年龄大于10岁的员工
    select * from staff_info where age > 10;
    2.再对他们按照部门分组统计平均薪资
    select post,avg(salary) from staff_info where age > 10 group by post;
    3.针对分组的结果做二次筛选
    select post,avg(salary) from staff_info where age > 10 group by post having avg(salary)>1000;
    4.最后按照指定字段排序
    select post,avg(salary) from staff_info where age > 10 group by post having avg(salary)>1000 order by avg(salary);
    image

    """
    当一条SQL语句中很多地方都需要使用聚合函数计算之后的结果 我们可以节省操作(主要是节省了底层运行效率 代码看不出来)
    select post,avg(salary) as avg_salary from emp where age > 10 group by post having avg_salary>1000 order by avg_salary;
    """
    

    查询关键字 -> limit 分页

    当表中数据特别多的情况下,我们很少会一次性获取所有的数据,我们根据需求来看,可能有的时候只需要一点点即可,因为分页的处理会减少数据的读取量,我们做了分页的设置也能降低减少多余的资源消耗
    

    select * from staff_info limit 3;
    直接展示从头开始的3条数据
    image

    select * from staff_info limit 3,3;
    从第三条数据之后,往后展示三条 相当与 前不取的意思
    image

    查询关键字 -> 正则表达式

    regexp为正则表达式的关键字 我们再这个关键字后面填写相应正则即可
    select * from staff_info where name regexp '^s';

    image

    多表查询的思路

    多表查询我们可以通过 表名.字段名的方法去查询
    我们先来创建一张表
    
    select * from staff1,department1;  会将两张表中所有的数据对应一遍
    这个现象我们也称之为'笛卡尔积' 无脑的对应没有意义 应该将有关系的数据对应到一起才合理
    基于笛卡尔积可以将部门编号与部门id相同的数据筛选出来
    涉及到两张及以上的表时 字段很容易冲突 我们需要在字段前面加上表名来指定
    基于上述的操作就可以将多张表合并到一起然后一次性获取更多的数据
    

    select * from staff1,department1 where staff1.dep_id=department1.id;
    image

    多表查询的方法

    方法1 多表连查

    我们还是使用
    department1 以及 staff1 这两个表进行操作演示
    select * from staff1
    +----+--------+--------+------+--------+
    | id | name   | sex    | age  | dep_id |
    +----+--------+--------+------+--------+
    |  1 | jason  | male   |   18 |    200 |
    |  2 | dragon | female |   48 |    201 |
    |  3 | kevin  | male   |   18 |    201 |
    |  4 | nick   | male   |   28 |    202 |
    |  5 | owen   | male   |   18 |    203 |
    |  6 | jerry  | female |   18 |    204 |
    +----+--------+--------+------+--------+
    
    mysql> select * from department1;
    +-----+--------------+
    | id  | name         |
    +-----+--------------+
    | 200 | 技术         |
    | 201 | 人力资源     |
    | 202 | 销售         |
    | 203 | 运营         |
    | 205 | 财务         |
    +-----+--------------+
    财务的id 我修改为205了!!!!!
    

    方式1
    连表操作
    inner join 内连接
    select * from staff1 inner join department1 on department1.id=staff1.dep_id;
    只连接两张表中公有的数据部分
    image

    我们应该在 inner 与 join 两侧写上 查询的表名
    只连接两张表中公有的数据部分
    在查询除了两表公共部分信息内容外,应该写 表名.字段名 这样的形式去筛选数据

    left join 左连接
    select * from staff1 left join department1 on department1.id=staff1.dep_id;
    以左表为基准 展示左表所有的数据 如果没有对应项则用NULL填充
    image

    right join 右连接
    select * from staff1 right join department1 on department1,id=staff1.dep_id
    以右表为基准 展示右表所有的数据 如果没有对应项则用NULL填充
    image

    image

    我们可以通过这一张图的显示来看出内连接 左连接 右连接 的区别

    全连接
    union
    select * from staff1 left join department1 on department1.id=staff1.dep_id union select * from staff1 right join department1 on department1.id=staff1.dep_id
    以左右表为基准 展示所有的数据 各自没有的全部NULL填充
    image

    '''
    学会了连表操作之后也就可以连接N多张表
    思路:将拼接之后的表起别名当成一张表再去与其他表拼接 再起别名当一张表 再去与其他表拼接 其次往复即可
    '''
    

    方式2
    子查询

    子查询就是将一条SQL语句用括号括起来当成另外一条SQL语句的查询条件
    例子:求姓名是nick的员工部门名称
    	子查询在此时就相当于我们日常解决问题的方式:
    	首先我们需要根据nick获取部门编号
    	select dep_id from staff1 where name='nick'
    	其次再根据部门表编号获取部门名称
    	select name from department1 where id=(select dep_id from staff1 where name='nick');
    

    image

    '在很多时候多表查询需要结合实际情况判断用那种,更多时候甚至是互相配合使用'
    

    额外知识点补充

    concat 连接
    主要用于分组之前的字段拼接操作

    select concat(name,'&',sex) from staff1;
    image

    concat_ws 主要用于拼接多个字段并且保持中间的连接符一致

    select concat_ws('&',name,age,sex) from staff1;
    image

    exists

    sql语句1 exists (sql语句2)
    sql语句2 有结果的情况下会执行sql语句1 如果没有结果则返回空数据
    

    select * from staff1 where exists (select name from department1);
    image


    __EOF__

  • 本文作者: 随风dd
  • 本文链接: https://www.cnblogs.com/ddsuifeng/p/16916202.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    动静态链接库
    shell_51.Linux获取用户输入_无显示读取,从文件中读取
    .NET 使用配置文件
    Golang时间
    一起学习 学习二叉树
    简化对象和函数写法
    我的创作纪念日
    R语言ggplot2可视化:可视化密度图(Density plot)、可视化多个分组的密度图、数据点分布在箱图中间、添加主标题、副标题、题注信息
    springboot+jsp大学图书借阅管理系统idea maven
    上万篇笔记总结丨小红书品牌高频投放的12种经典笔记形式
  • 原文地址:https://www.cnblogs.com/ddsuifeng/p/16916202.html