zoukankan      html  css  js  c++  java
  • MySQL第四讲

    昨日内容回顾

    • 表与表之间建关系(外键)

      """
      表与表之间最多只有四种关系
      	一对多
      	多对多
      	一对一
      	没有关系
      
      在确定表与表之间的关系的时候记住一句话
      	换位思考
      """
      # 一对多(一对多、多对一都叫	一对多)
      """
      一对多关系字段放在多的一方
      以员工表和部门表
      	员工表就是多的一方 所以外键字段应该建在员工表里面
      """
      站在两张表的基础之上 只有一方成立 那么就是一对多
      create table dep(
      	id int primary key auto_increment,
          dep_name char(16),
          dep_desc char(32)
      );
      create table emp(
      	id int primary key auto_increment,
          name char(16),
          age int,
          dep_id int,
          foreign key(dep_id) references dep(id)
      )
      
      # 多对多
      站在两张表的基础之上 双方都成立 那么就是多对多
      多对多需要创建第三张关系表来存储两张表的关系,两张表自身没有任何额外字段
      """
      以图书表和作者表为例
      	多对多外键字段放在第三张表中
      """
      create table book(
      	id int primary key auto_increment,
          title char(16),
          price float(10,2)
      );
      create table author(
      	id int primary key auto_increment,
          name char(16),
          age int
      );
      create table book2author(
      	id int primary key auto_increment,
          
          book_id int,
          foreign key(book_id) references book(id)
          on update cascade
          on delete cascade,
          
          author_id int,
          foreign key(author_id) references author(id)
          on update cascade
          on delete cascade
      )
      
      # 一对一
      """
      以用户与用户详情
      
      针对一对一的外键关系 外键字段建在任意一方都可以
      但是我们推荐你建在查询频率/使用频率较高的那张表
      """
      站在双方的角度都不成立			一对一/没有关系
      create table user(
      	id int primary key auto_increment,
          name char(64) default 'jason',
          gender enum('male','female','others') default 'male',
          
          user_detail_id int unique,
          foreign key(user_detail_id) references user_detail(id)
          on update cascade
          on delete cascade
      )
      
      create table user_detail(
      	id int primary key auto_increment,
          phone int,
          addr char(64)
      )
      
    • 外键注意事项

      1.必须先创建被关联表(dep表)
      
      2.录入数据的时候也是先录入被关联表的数据(dep表)
      
      3.想要有关系的数据同步更新同步删除
      create table emp(
      	id int primary key auto_increment,
          name char(16),
          age int,
          dep_id int,
          foreign key(dep_id) references dep(id)
          on update cascade
          on delete cascade
      )
      
    • 其他需要了解的sql语句操作

      主要是针对表的操作
      
      1.修改表名
      alter table t1 rename t666;
      
      2.添加字段
      alter table t666 add password int;
      alter table t666 add gender char(4) first;
      alter table t666 add age int after name;
      
      3.修改字段
      alter table t666 modify password  bigint;
      alter table t666 change password  pwd int;
      
      4.删除字段
      alter table t666 drop pwd;
      
    • 复制表(了解)

      """
      我们sql语句执行的结果可以把它看成是一张虚拟表
      """
      create table t1 select * from t666;
      # 将t666的数据复制到t1中了 但是没有外键、主键、索引....
      
    • 作业

      1.书籍表和出版社表(版权问题一本书不能被多个出版社出版)
        	一本书能否对应多个出版社 		不可以
        	一个出版社能否对应多本书		可以	
        	一对多
          	多:书
          	一:出版社
        	外键字段建在书的一方
           
      2.文章表和文章分类表(按男女分类...)
      	一遍文章能够对应多个分类		不可以
          一个分类能否对应多个文章		可以
          一对多
          	多:文章
              一:分类
          外键字段建在文章的一方
          
      3.文章表和文章标签表(一个人可以有多个标签)
      	一遍文章可以有多个标签			可以
          一个标签能否对应多个文章        可以
         	多对多
          	需要创建第三张关系表
      
          
      4.作者表和作者详情表
      	一对一
      

    今日内容概要

    • 单表操作

      select
      from 
      where
      group by
      having
      distinct
      order by
      limit
      ...
      
    • 多表操作

      1.子查询
      2.联表查询
      

    今日内容详细

    前期表及数据准备

    create table emp(
      id int primary key auto_increment,
      name varchar(20) not null,
      sex enum('male','female') not null default 'male', #大部分是男的
      age int unsigned not null default 28,
      hire_date date not null,
      post varchar(50),
      post_comment varchar(100),
      salary double(15,2),
      office int, #一个部门一个屋子
      depart_id int
    );
    
    
    # 插入数据
    insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
    ('jason','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);
    
    
    ps:
    select * from emp;
    select * from empG;
    *************************** 16. row ***************************
              id: 16
            name: 程咬银
             sex: female
             age: 18
       hire_date: 2013-03-11
            post: operation
    post_comment: NULL
          salary: 19000.00
          office: 403
       depart_id: 3
    *************************** 17. row ***************************
    
    """
    如果在windows系统中,插入中文字符,select的结果为空白,可以将所有字符编码统一设置成gbk
    
    将配置文件中所有的编码由原来的utf8换成gbk
    然后重启mysql服务端
    """
    

    sql语句书写顺序和执行顺序

    select name,salary from emp where id < 5;
    
    # 执行顺序
    from  		1.先确定从哪张表找数据
    where		2.再根据where后面的条件筛选
    select      3.再获取指定的字段对应的数据
    

    where筛选

    """
    and 与		and连接的条件必须都满足
    or  或		or连接的条件满足一个就可以
    not 非		not取反
    """
    
    # where后面跟得其实就是筛选条件
    
    # 1.查询id大于等于3小于等于6的数据
    select * from emp where id >= 3 and id <= 6 ;
    select *  from emp where id between 3 and 6;  # 随你自己
    
    # 2.查询薪资是20000或者18000或者17000的数据
    select * from emp where salary=20000 or salary=18000 or salary=17000;
    select * from emp where salary in (20000,18000,17000);
    
    # 3.查询员工姓名中包含o字母的员工姓名和薪资
    """
    模糊匹配
    	关键字  like
    		
    	特殊符号
    		%	匹配任意个数的任意字符			
    		_	匹配一个任意字符
    """
    select name,salary from emp where name like '%o%';
    
    mysql> select name,salary from emp where name like '%o%';
    +-------+------------+
    | name  | salary     |
    +-------+------------+
    | jason |    7300.33 |
    | tom   | 1000000.31 |
    | tony  |    3500.00 |
    | owen  |    2100.00 |
    +-------+------------+
    mysql> select name,salary from emp where name like 'o%';
    +------+---------+
    | name | salary  |
    +------+---------+
    | owen | 2100.00 |
    +------+---------+
    mysql> select name,salary from emp where name like '%o'; 
    
    # 4.查询员工姓名是由四个字符组成的员工姓名与其薪资
    select name,salary from emp where name like '%%%%';  不行!!!
    select name,salary from emp where name like '____';
    
    # 5.查询id小于3或者大于6的数据
    select * from emp where id < 3 or id > 6; 
    
    # 6.查询薪资不在20000,18000,17000的数据
    select * from emp where salary not in (20000,18000,17000);
    
    # 7.查询岗位描述为空的员工名与岗位名 
    select name,post from emp where post_comment=NULL;  没有效果!!!
    select name,post from emp where post_comment is NULL; 
    针对null不能用等号,只能用is
    
    

    group by分组

    """
    聚合函数
    	max		求最大值
    	min		求最小值
    	avg		求平均值
    	sum		求和
    	count	统计个数
    
    聚合函数只能在分组之后使用
    """
    
    
    # 数据分组应用场景:每个部门的平均薪资,男女比例等
    """
    将个体按照组 组成一个个的整体
    然后就以整体为单位操作
    """
    # 1.按部门分组
    select * from emp group by post;  # group by后面跟什么就按照什么分组
    """
    分组之后默认情况下不应该再直接获取到组内单个元素的数据,而是只能获取分组的依据
    	按照部门分组的话 那么你就只能获取到部门
    
    5.6及之前的版本 没有设置严格模式 分组之后数据随便拿也不报错
    5.6之后的版本的 分组之后select后面只能写分组的依据 不能直接写其他字段
    """
    set global sql_mode="strict_trans_tables,only_full_group_by";
    退出客户端重新进入即可
    
    mysql> select * from emp group by post;
    ERROR 1055 (42000): 'day04.emp.id' isn't in GROUP BY
    
    mysql> select name from emp group by post;
    ERROR 1055 (42000): 'day04.emp.name' isn't in GROUP BY
    
    mysql> select salary from emp group by post;
    ERROR 1055 (42000): 'day04.emp.salary' isn't in GROUP BY
    
    mysql> select post from emp group by post;
    +-----------------------------+
    | post                        |
    +-----------------------------+
    | operation                   |
    | sale                        |
    | teacher                     |
    | 张江第一帅形象代言             |
    +-----------------------------+
    '''
    # 1 获取每个部门的最高工资 
    select max(salary) from emp group by post;
    
    mysql> select post,max(salary) from emp group by post;
    +-----------------------------+-------------+
    | post                        | max(salary) |
    +-----------------------------+-------------+
    | operation                   |    20000.00 |
    | sale                        |     4000.33 |
    | teacher                     |  1000000.31 |
    | 张江第一帅形象代言          |     7300.33 |
    +-----------------------------+-------------+
    
    mysql> select post,max(salary) as '最高薪资' from emp group by post;
    +-----------------------------+--------------+
    | post                        | 最高薪资     |
    +-----------------------------+--------------+
    | operation                   |     20000.00 |
    | sale                        |      4000.33 |
    | teacher                     |   1000000.31 |
    | 张江第一帅形象代言          |      7300.33 |
    +-----------------------------+--------------+
    
    mysql> select post as '部门',max(salary) as '最高薪资' from emp group by post;
    +-----------------------------+--------------+
    | 部门                        | 最高薪资     |
    +-----------------------------+--------------+
    | operation                   |     20000.00 |
    | sale                        |      4000.33 |
    | teacher                     |   1000000.31 |
    | 张江第一帅形象代言          |      7300.33 |
    +-----------------------------+--------------+
    
    # 每个部门的最低工资
    select post,min(salary) from emp group by post;
    
    # 每个部门的平均工资
    select post as '部门', avg(salary) as '平均工资' from emp group by post;
    
    # 每个部门的员工人数
    select post as '部门',count(id) as '员工人数' from emp group by post;
    
    # 3.查询分组之后的部门名称和每个部门下所有的学生姓名
    select post,group_concat(name) from emp group by post;
    select post,group_concat(name,'_NB') from emp group by post;
    select post,group_concat(name,':',salary) from emp group by post;
    
    
    """
    数据的拼接操作
    	分组之后可以使用
    		group_concat
    	分组之前可以使用
    		concat
    """
    # 4.补充concat(不分组时用)拼接字符串达到更好的显示效果 as语法使用
    select name as 姓名,salary as 薪资 from emp;
    select concat("NAME: ",name) as 姓名,concat("SAL: ",salary) as 薪资 from emp;
    
    

    分组注意事项

    select id,name,age from emp where max(salary) > 3000;   不能这么用
    
    select max(salary) from emp;  
    不分组的情况下默认整体就是一组 可以在select的后面使用聚合函数
    
    
    8、统计各部门年龄在30岁以上的员工平均工资
    # 1.先拿到所有年龄大于30岁的员工数据
    select * from emp where age > 30;  
    # 2.再按照部门分组 得到年龄大于30岁的部门
    select post,group_concat(name) from emp where age > 30 group by post; 
    
    # 最终完成
    select post,avg(salary) from emp where age > 30 group by post; 
    

    having分组之后过滤

    """
    	where
    	having
    	两者的功能都是筛选数据 是一样的
    	但是两者的使用场景不一样
    	where分组之前使用
    	having分组之后使用
    """
    1、统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门
    select post,avg(salary) from emp 
    	where age > 30  # 1 先筛掉年龄小于30的
        group by post   # 2 得到30岁以上的员工组成的部门
        having avg(salary) > 10000;
        
    """
    1.from 
    2.where
    3.group by 
    4.having
    5.select
    """
    #强调:having必须在group by后面使用
    select * from emp having avg(salary) > 10000;  # 报错
    

    distinct去重

    """
    distinct去重
    	必须是完全一样的数据才能去重
    """
    select distinct id,age from emp;  # 包含id肯定无法去重
    

    order by排序

    # 按照年龄排序
    select * from emp order by age;  # 默认 升序(从小到大)		asc
    select * from emp order by age asc;  # 升序
    select * from emp order by age desc;  # 降序 
    # 单个条件比不出大小 可以比多个
    select * from emp order by age,salary;  # 第一个字段比不出来就用第二个
    select * from emp order by age,salary desc;
    
    
    # 统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门,然后对平均工资进行排序
    select post,avg(salary) from emp 
    	where age > 10 
        group by post
        having avg(salary) > 1000
        order by avg(salary);
    

    limit限制展示条数

    select * from emp limit 5;  # 只要最开始的五条
    select * from emp limit 0,5;
    select * from emp limit 5,5;
    select * from emp limit 起始位置,展示条数;
    

    正则

    我们的sql语句中也支持你书写正则表达式
    """
    就是用特殊的符号 来帮你去一大段文本中匹配对应的内容
    """
    select * from emp where name regexp '^j.*(n|y)$';
    
    '^j.*(n|y)$':查看以字母j开头 字母n或者y结尾的字符串
    

    多表操作

    #建表
    create table dep(
    id int primary key auto_increment,
    name varchar(20) 
    );
    
    create table emp(
    id int primary key auto_increment,
    name varchar(20),
    sex enum('male','female') not null default 'male',
    age int,
    dep_id int
    );
    
    #插入数据
    insert into dep values
    (200,'技术'),
    (201,'人力资源'),
    (202,'销售'),
    (203,'运营');
    
    insert into emp(name,sex,age,dep_id) values
    ('jason','male',18,200),
    ('egon','female',48,201),
    ('kevin','male',18,201),
    ('nick','male',28,202),
    ('owen','male',18,203),
    ('jerry','female',18,204);
    
    
    select * from dep,emp;  # 结果是一个笛卡尔积(不需要掌握)
    
    select * from dep,emp where dep.id = emp.dep_id;  # 一定要加表前缀
    

    连表操作

    """
    inner join
    left join
    right join
    union
    """
    # inner join	内连接		只按照两张表都有的数据拼接(没有的就都不拼接)
    select * from dep inner join emp on dep.id = emp.dep_id;
    
    # left join    左连接		以左表为基准展示所有的数据(没有对应的用NULL代替)
    select * from dep left join emp on dep.id = emp.dep_id;
    
    # right join   右连接		以右表为基准展示所有的数据(没有对应的用NULL代替)
    select * from dep right join emp on dep.id = emp.dep_id;
    
    # union
    select * from dep left join emp on dep.id = emp.dep_id
    union
    select * from dep right join emp on dep.id =emp.dep_id
    为了舒适的结果,眼前的坎坷路程即使再长都是值得的。
  • 相关阅读:
    java.io.IOException: HTTPS hostname wrong: should be 规格严格
    linux syslog 规格严格
    SVN,HG,GIT 命令说明 规格严格
    pclose : no child process 规格严格
    使用NetBeans6开发OSGi应用(1)——FirstOSGi[88250原创]
    Netbeans大战Eclipse 谁将走向祭坛?
    XP中的重要惯例和规则
    使用NetBeans6开发OSGi应用(1)——FirstOSGi[88250原创]
    简简单单删除所有.svn目录
    简简单单删除所有.svn目录
  • 原文地址:https://www.cnblogs.com/abudrSatan1998/p/13404654.html
Copyright © 2011-2022 走看看