【数据分析】【MySQL】快速入门+案例+代码+命令整理+GIF实操演示

1.SQL的语句顺序(理论)

SELECT [ALL|DISTINCT] <目标表达式>....
FROM <表名或者视图名>..
[WHERE <条件表达式>]
[GROUP BY <列名 1> [HAVING] <条件表达式>]
[ORDER BY <列名 2> [ASC|DESC]]

2.SQL数据库的选择命令

2.1 数据库的选择(实操)

作用 命令
查看当前有哪些数据库 show databases;
选择数据库 use database_name;
查看当前使用的是哪个数据库 select database();
新建数据库 create database database_name;
删除数据库 drop database database_name;
数据库选择演示

2.2 数据库的表格选择命令(实操)

作用 命令
查看当前数据库有哪些表格 show tables;
在当前数据库新建表格 create table table_name(字段名1 字段类型, 字段名2 字段类型);
为当前数据库的表格插入数据 insert into 表格名 values ('字段名1的值',字段名2的值,'字段名3的值');
更新当前数据库某个表的数据 update 表格名 set 字段名1="值1" where 字段名1="值2";
删除当前数据库某个表的数据 delete from 表名 where name="值1";
删除当前数据库的某个表格 drop table table_name;
表格选择演示

3. 数据库建表约束条件(理论+说明)

作用 详细 说明 命令
主键约束 单一主键 给某个字段添加约束,使得该字段不重复且不为空 create table user(
   id int primary key,
   name varchar(4));
联合主键 多个字段加起来唯一 create table user2(
   id int,
   name varchar(4),
    password varchar(20),
   primary key(id,name));
自增约束 控制某个值自动增长 create table user3(
   id int primary key auto_increment,
   name varchar(4));
唯一约束 单一约束 约束字段的值不能重复 create table user4(
   id int,
   name varchar(4) unique);
联合唯一约束 多个字段加起来的值唯一 create table user5(
   id int,
   name varchar(4),
   unique(id,name));
非空约束 非空约束 修饰字段的值不能为空 create table user6(
   id int,
   name varchar(4) not null);
默认约束 默认约束 当我们传入字段值的时候,如果没有传值,就会使用默认值 create table user7(
   id int,
   name varchar(4),
   age int default 23);
外键约束 外键约束 针对两张表:主表和附表,附表会参考主表的某个字段作为两张表的连接 create table coutries(
   id int primary key,
   name varchar(10));

create table provinces(
   id int primary key,
   name varchar(10),
   country_id int,
   foreign key(country_id) references country(id));
修改约束 添加约束 为字段加上新的约束 alter table user4 add primary key(id);
修改约束 修改字段的约束(也可视作添加约束) alter table user6 modify id int primary key auto_increment;
删除约束 删除约束 删除某个字段的约束 alter table user3 drop primary key;

4. 数据库的设计范式(理论+实例)

  • 第一范式
    数据表中的所有字段都是不可分割的原子值。字段值还可以继续拆分的,就不满足第一范式。
    -- 不满足第一范式
    create table student2(
          id int primary key,
          name varchar(20),
          address varchar(30));
    
      insert into student2 values(1,'卯月','中国四川省成都市武侯区武侯大道100号');
      insert into student2 values(2,'竹秋','中国四川省成都市武侯区武侯大道90号');
      insert into student2 values(3,'花朝','中国四川省成都市武侯区武侯大道80号');
    
    -- 满足第一范式
    create table student3(
          id int primary key auto_increment,
          name varchar(20),
          country varchar(20),
          province varchar(20),
          city varchar(20),
          street varchar(20),
          num varchar(10));
      insert into student3 values(1,'卯月','中国','四川省','成都市','武侯区','武侯大道100号');
      insert into student3 values(2,'竹秋','中国','四川省','成都市','武侯区','武侯大道90号');
      insert into student3 values(3,'花朝','中国','四川省','成都市','武侯区','武侯大道80号');
    
  • 第二范式
    必须是满足第一范式的前提下,第二范式要求,除主键外的每一列都必须完全依赖于主键。如果要出现不完全依赖,只可能发生在联合主键的情况下。
    -- 不满足第二范式
    create table myorder(
          product_id int,
          customer_id int,
          product_name varchar(20),
          customer_name varchar(20),
          primary key(product_id,customer_id));
    
    -- 满足第二范式
    -- order id 和 product_id,customer_id 拆分开,可以保证下面两个表里面的name满足第二范式
    create table myorder(
          order_id int primary key,
          product_id int,
          customer_id int
          );
      create table product(
          id int primary key,
          name varchar(20));
      create table customer(
          id int primary key,
          name varchar(20));
    
  • 第三范式
    必须先满足第二范式,除开主键列的其他列之间不能有传递依赖关系。
    -- 不满足第三范式
    create table myorder(
              order_id int primary key,
              product_id int,
              customer_id int,
              customer_phone varchar(11)
              ); # 错误,customer_phone可能还依赖于customer_id
    
    -- 满足第三范式
    -- customer_phone 只和 customer表里面的id有关
    create table myorder(
              order_id int primary key,
              product_id int,
              customer_id int
              ); 
    
    create table customer(
              id int primary key,
              name varchar(20),
              customer_phone varchar(11));
    
  • 注意
    三大范式并不是必须要满足,可以基于我们的业务需求进行调整。但是在设计mysql表的时候要尽量考虑到我们的三大范式规则。

5. 数据库查询(重点+实操)

5.1 创造数据(案例+演示)

5.1.1 说明

首先使用MySQL创建三个简单的表模拟一个跨国公司的人员薪资表(极简版本),会用到Python自动生成数据的一个自定义算法,因此需要确保自己安装有python,同时安装有pandas、sqlalchemy、pymysql、jupyter notebook三方包。(后续写数据分析的总结也会用到,因此建议直接安装一个Anaconda到电脑上,就可以一次性解决上述问题)

5.1.2 创建表
-- 国家表
create table countries(
  id int ,
  name varchar(10),
  primary key(id)
);

-- 部门表
create table departments(
  id int primary key,
  name varchar(10)
);

-- 人员薪资表
create table staff(
  id int primary key,
  name varchar(10),
  job varchar(10),
  age int(3),
  salary decimal,
  country_id int,
  department_id int,
  foreign key(country_id) references countries(id),
  foreign key(department_id) references departments(id)
);
5.1.3 填充数据
  • 首先使用mysql填充国家表和部门表
    -- 国家表
    insert into countries values
      (1,'中国'),
      (2,'日本'),
      (3,'韩国'),
      (4,'柬埔寨'),
      (5,'越南'),
      (6,'泰国'),
      (7,'缅甸'),
      (8,'印度尼西亚'),
      (9,'马来西亚'),
      (10,'美国'),
      (11,'英国'),
      (12,'德国'),
      (13,'意大利'),
      (14,'俄罗斯'),
      (15,'斯洛文尼亚'),
      (16,'捷克'),
      (17,'波兰'),
      (18,'乌克兰'),
      (19,'加拿大'),
      (20,'印度'),
      (21,'巴基斯坦');
    
    -- 部门表
    insert into departments values
      (1,'董事会'),
      (2,'行政办公室'),
      (3,'人力资源部'),
      (4,'财务部'),
      (5,'生产技术部'),
      (6,'计划营销部'),
      (7,'安全监察部'),
      (8,'后勤部'),
      (9,'组织部'),
      (10,'保卫部');
    
  • 使用jupyter notebook填充staff表
    import random
    import pandas as pd
    
    last_names = ['卯月','竹秋','花朝','殷正','赵','钱','孙','李','周','吴','郑','王','毛','胡','董','杨','鲍','崔','袁']
    first_names = ['七','初一','十五','德','智','体','美','全','面','发','展']
    ages = [i for i in range(18,40)]
    careers = ['实习生','UI','前端','后端','开发','测试','算法','数据分析','老板','主管']
    salarys = random.sample(range(10000,100000),100)
    
    def generateRow(num_id,last_names,first_names,ages,careers,salarys):
        last_name = random.choice(last_names)
        first_name = random.choice(first_names)
        name = last_name + first_name
        age = str(random.choice(ages))
        career = random.choice(careers)
        salary = str(random.choice(salarys))
        country_id = random.choice(range(1,22))
        department_id = random.choice(range(1,11))
        return [num_id,name,career,age,salary,country_id,department_id]
    
    datas = []
    for i in range(10000):
        row = generateRow(i+1,last_names,first_names,ages,careers,salarys)
        datas.append(row)
      
    infos = pd.DataFrame(datas,columns=['id','name','job','age','salary','country_id','department_id'])
    infos.to_sql(name='staff',con='mysql+pymysql://root:123456@localhost:3306/summary',
                if_exists='append',index=False)
    
5.1.4 生成数据

复制上方代码到对应的mysql命令行,jupyter notebook中,可以自行生成。


生成数据演示

5.2 初级查询(代码+不演示)

  • 查询顺序

    SELECT [ALL|DISTINCT] <目标表达式>....  -- 查询
    FROM <表名或者视图名>..  -- 数据从哪来
    [WHERE <条件表达式>]  -- 有什么筛选条件
    [GROUP BY <列名 1> [HAVING] <条件表达式>]  -- group by通过什么分组,having 筛选条件
    [ORDER BY <列名 2> [ASC|DESC]]  -- 通过什么进行怎样的排序
    
  • 查询country表中的所有信息

    select * from countries;
    
  • 查询contry表里有哪些国家

    select name from countries;
    
  • 查询国家中不重复的name

    select distinct name from countries;
    
  • 查询编号在1~10的国家

    select * from countries where id between 0 and 11;
    
    select * from countries where id < 11;
    
  • 查询countries表中中国,日本、韩国的所有信息

    select * from countries where name in ('中国','日本','韩国');
    
  • 查询staff表中,做算法工作或者年龄在23岁的人的所有信息

    select * from staff where job='算法' or age=23;
    
  • 查询staff表中,做算法工作并且年龄为23岁的人的所有信息

    select * from staff where job='算法' and age=23;
    
  • id降序排列countries表中的所有信息

    select * from countries order by id desc;
    
  • 以id升序,name降序排列countries表中的所有信息

    select * from countries order by id asc,name desc;
    
  • 查询staff表中算法工作的人数

    select count(*) from staff where job='算法';
    

5.3 子查询(实例+代码+演示)

5.3.1 说明

子查询可以理解为多个查询的堆叠,将上一个查询的结果作为下一个查询的筛选条件或者作为下一个查询的数据来源。

5.3.2 实例和演示
  • 查询staff表中年龄最大的人们的姓名和薪资

    -- step 1,首先找到最大年龄
    select max(age) from staff;
    -- step 2,根据找到的最大年龄,让它作为下一个查询的条件
    select name,salary from staff where age = (select max(age) from staff);
    
     -- 完整版
    select name,salary from staff where age = (select max(age) from staff);
    
    查询staff表中年龄最大的人们的姓名和薪资
  • 查询每个部门的平均薪资

    -- step 1 按照部门分组
    select * from staff group by department_id;
    -- step 2 求平均薪资
    select avg(salary) from staff group by department_id;
    
    -- 完整版
    select avg(salary) from staff group by department_id;
    
求每个部门的平均薪资
  • 查询以卯月为姓的各个工作人员的部门平均薪资、部门id
    select department_id,avg(salary) from staff where name like '卯月%' group by department_id;
    
各部门以卯月为姓的平均薪资和id

5.4 多表链接查询

  • 查询各部门的平均薪资及部门名称
    -- step1 部门名称在departments表里面,薪资在staff表里面。可以先查看各自的内容
    select name from departments;
    select salary from staff;
    
    -- step2 在我们建表的时候,使用了department_id作为外键连接了departments表。因此可以使用为连接
    select departments.name,avg(salary)
    from departments,staff
    where departments.id = staff.department_id
    group by staff.department_id;
    
    -- 注意,一定不能弄混淆各个表的列名,可以使用表名.列名的方式进行指定,防止混淆
    
查询各部门的平均薪资及部门名称
  • 查询所有以卯月为姓的人所在的国家名称、部门名称、姓名、年龄、工作和薪资
    select countries.name,departments.name,staff.name,age,job,salary
    from countries,departments,staff
    where countries.id = staff.country_id and departments.id = staff.department_id
    having staff.name like '卯月%';
    
    -- 详解
    首先,我们要获得国家名称和部门名称,就必须要从countries和departments表中获得名字。
    因此是一个三表链接的查询。之后,我们根据三表间的外键进行连接。
    使用where语句连接了三表,having语句进行以卯月为姓的筛选,最终得到结果。
    
    查询以卯月为姓的人所在的国家、部门、姓名、年龄、工作和薪资
  • 查询在中国工作的,以卯月为姓的,在组织部发展的员工的姓名、年龄、工作和薪资
    select * 
    from (select countries.name country_name,departments.name department_name, staff.name staff_name,age,job,salary
    from countries,departments,staff
    where countries.id = staff.country_id and departments.id = staff.department_id
    having staff.name like '卯月%') a
    where a.country_name = '中国' and department_name = '组织部';
    
    -- 详解
    首先借助上一次查询我们获得的信息,作为一个数据来源,取个别名叫做a。
    同时,为了防止name之间的混淆,我们将country_name,department_name,staff_name分别作为三个别名添加上
    最后我们再利用前面命令好的别名直接进行指代数据库查找中国,组织部的姓卯月的人的信息
    
查找在中国工作的,组织部的姓卯月的员工的信息

5.5 综合查询

  • 查询薪资在5万以上,7万以下员工中以卯月为姓的员工信息
    select *
    from (select departments.name department_name,staff.name staff_name,age,job,salary
    from departments,staff
    where departments.id = staff.department_id) a
    where a.staff_name like '卯月%' and a.salary between 50000 and 70000;
    
    -- 详解
    首先拿到员工算法部门和员工信息的合表,作为数据来源,之后再根据条件查找薪资和姓氏。
    
    -- 注意
    查询方法不唯一,可以有更多方式,只要符合内在语法逻辑即可。因此,mysql调优也很好玩,不展开。
    
查询薪资在5万及7万间的员工信息
  • 查询薪资在5万以上,7万以下员工中以卯月为姓的员工各部门平均薪资
    select department_name,avg(salary)
    from (select departments.name department_name,staff.name,salary
    from departments,staff
    where departments.id = staff.department_id and salary between 50000 and 70000
    having staff.name like '卯月%') a
    group by a.department_name;
    
    
    -- 详解
    首先我们可以先取出部门名称,以卯月为姓,薪资在50000到70000之间的员工信息作为下一次查询的数据来源;
    之后我们再对数据按照部门名称进行排序。注意,因为staff.name行数明显不重复数目大于department_name 行数,所以无法显示staff.name。
    
薪资在5万以上,7万以下员工中以卯月为姓的员工各部门平均薪资

-- 查询高于财务部以卯月为姓的员工的平均薪资的员工信息

-- 首先,我们可以找到财务部以卯月为姓的员工的平均薪资
select avg(salary)
from staff,departments 
where departments.id = staff.department_id and departments.name = '财务部' and staff.name like '卯月%';


-- 之后,将平均薪资作为查询条件,找薪资高于平均薪资的员工
select * 
from staff
where salary > (
  select avg(salary)
  from staff,departments 
  where departments.id = staff.department_id and departments.name = '财务部' and staff.name like '卯月%');
查询高于财务部以卯月为姓的员工的平均薪资的员工信息
  • 显示国家和部门的联合信息
    select name from countries
    union
    select name from departments;
    
国家和部门的联合信息

5.6 连接查询

作用 详细 说明 命令
内连接 内连接 查找两张表都有的内容 inner join

join
外连接 左连接 只显示左边表有的相关数据 left join

left outer join
右连接 只显示右边表有的相关数据 right join

right outer join
完全外连接 两边表都显示 full join

full outer join
5.6.1 创建数据

创建两张表(极简版本):
一张表是课程表,包含课程编号,课程名称;
一张表是教师表,包含教师编号、教师姓名,课程编号;

create table courses(
  id int,
  c_name  varchar(10)
);

insert into courses values
  (1,'语文'),
  (2,'数学'),
  (3,'英语'),
  (4,'政治'),
  (5,'历史'),
  (6,'地理'),
  (7,'物理'),
  (8,'生物'),
  (9,'化学');

create table teachers(
  id int,
  c_id int,
  t_name varchar(10)
);

insert into teachers values
  (1,3,'卯月七'),
  (2,5,'卯月初一'),
  (3,6,'卯月初二'),
  (4,1,'卯月初三'),
  (5,2,'卯月初四'),
  (6,5,'卯月初五'),
  (7,1,'卯月初六'),
  (8,2,'卯月初七'),
  (9,3,'卯月初八'),
  (10,4,'卯月初九'),
  (11,3,'卯月十五');
5.6.2 内连接

查询两张表的交叉数据

-- 对于courses表和teachers表来说,在teachers表中没有7、8、9的课程编号,因此不会出现物理、生物、化学三科。
select * from teachers inner join courses on teachers.c_id = courses.id;
内连接
5.6.3 外连接
  • 左连接
    以左边为基准显示相关数据
    -- teachers表左连接courses表
    -- 以teachers表为基准显示
    select * from teachers left join courses on teachers.c_id = courses.id;
    
    -- courses表左连接teachers表
    -- 以courses表为基准
    select * from courses left join teachers on teachers.c_id = courses.id;
    
左连接
  • 右连接
    以右边为基准显示相关数据
    select * from teachers right join courses on teachers.c_id = courses.id;
    
    select * from courses right join teachers on teachers.c_id = courses.id;
    
右连接
  • 全连接
    mysql 数据库不支持全连接,可以使用union达到要求
    select id,c_name from courses
    union
    select id,t_name from teachers; 
    
mysql全连接的实现

说明

  • 本文由我本人原创,发布于简书卯月七账号、知乎卯月七账号、CSDN卯月七账号。
  • 本文允许转载、学习,转载请注明出处,谢谢。
  • 作者邮箱mcj6989@163.com,有问题可以联系。
  • 本文为我整理的MySQL的入门文章,更多知识可以购买专业书籍学习。
  • 创作不易,如果对你有帮助,希望能给我一些反馈,包括不限于点赞,评论,转发,非常感谢!!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容