数据库 4

上节回顾:

  1. mysql停止的流程,多实例在不知root密码情况下通过命令行是否能停止
    sql语句在查询不到数据时的执行流程

  2. 如何手动停止手动开启的数据库;如何从8.0降级到5.7
    mysqladmin -uroot -p -S /tmp/xxx shutdown

3.配合多子句
select from where group by
where
=

< >= <=
like 'aaa%'
and or in
between and

group by + 聚合函数
一张大表中,需要对具有共同条件的数据,进行分组统计工作.
max()
min()
count()
sum()
avg()
group_concat

显示表数据时,不能1对多的显示,5.7中通过sql_mode=ONLY_fULL_GROUP_BY

====================================
from where group by having order by limit

  1. having 后过滤
    --- 统计中国每个省的总人口数,只显示总人口大于500w
    SELECT district , SUM(population)
    FROM city
    WHERE countrycode='CHN'
    GROUP BY district
    HAVING SUM(population)>5000000;
  1. order by
    --- 查询中国所有的城市信息,并按照人口数排序输出结果
    SELECT * FROM city
    WHERE countrycode='CHN'
    ORDER BY population DESC ;
    --- 统计中国每个省的总人口数,只显示总人口大于500w,并按照总人口降序输出
    SELECT district , SUM(population)
    FROM city
    WHERE countrycode='CHN'
    GROUP BY district
    HAVING SUM(population)>5000000
    ORDER BY SUM(population) DESC ;
  1. LIMIT
    --- 统计中国每个省的总人口数,只显示总人口大于500w,并按照总人口降序输出前5名
    SELECT district , SUM(population)
    FROM city
    WHERE countrycode='CHN'
    GROUP BY district
    HAVING SUM(population)>5000000
    ORDER BY SUM(population) DESC
    LIMIT 10;

SELECT district , SUM(population)
FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>5000000
ORDER BY SUM(population) DESC
LIMIT 2,3;

SELECT district , SUM(population)
FROM city
WHERE countrycode='CHN'
GROUP BY district
HAVING SUM(population)>5000000
ORDER BY SUM(population) DESC
LIMIT 4 OFFSET 2;

  1. distinct 去重复
    mysql> select distinct countrycode from city ;

  2. union && union all
    SELECT * FROM city WHERE countrycode='CHN' OR countrycode='USA';
    SELECT * FROM city WHERE countrycode IN ('CHN' ,'USA');

SELECT * FROM city WHERE countrycode='CHN'
UNION ALL
SELECT * FROM city WHERE countrycode='USA';

union : 去重复
union all : 不去重复

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

  1. 多表连接查询

7.0 多表连接准备

按需求创建一下表结构:
use school

student :学生表
sno: 学号
sname:学生姓名
sage: 学生年龄
ssex: 学生性别

teacher :教师表
tno: 教师编号
tname:教师名字

course :课程表
cno: 课程编号
cname:课程名字
tno: 教师编号

score :成绩表
sno: 学号
cno: 课程编号
score:成绩
============================================

CREATE DATABASE school CHARSET utf8;
USE school

CREATE TABLE student(
sno INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '学号',
sname VARCHAR(20) NOT NULL COMMENT '姓名',
sage TINYINT UNSIGNED NOT NULL COMMENT '年龄',
ssex ENUM('f','m') NOT NULL DEFAULT 'm' COMMENT '性别'
)ENGINE=INNODB CHARSET=utf8;

CREATE TABLE course(
cno INT NOT NULL PRIMARY KEY COMMENT '课程编号',
cname VARCHAR(20) NOT NULL COMMENT '课程名字',
tno INT NOT NULL COMMENT '教师编号'
)ENGINE=INNODB CHARSET utf8;

CREATE TABLE sc (
sno INT NOT NULL COMMENT '学号',
cno INT NOT NULL COMMENT '课程编号',
score INT NOT NULL DEFAULT 0 COMMENT '成绩'
)ENGINE=INNODB CHARSET=utf8;

CREATE TABLE teacher(
tno INT NOT NULL PRIMARY KEY COMMENT '教师编号',
tname VARCHAR(20) NOT NULL COMMENT '教师名字'
)ENGINE=INNODB CHARSET utf8;

INSERT INTO student(sno,sname,sage,ssex)
VALUES
(1,'zhang3',18,'m'),
(2,'zhang4',18,'m'),
(3,'li4',18,'m'),
(4,'wang5',19,'f'),
(5,'zh4',18,'m'),
(6,'zhao4',18,'m'),
(7,'ma6',19,'f');
(8,'oldboy',20,'m'),
(9,'oldgirl',20,'f'),
(10,'oldp',25,'m');

INSERT INTO teacher(tno,tname) VALUES
(101,'oldboy'),
(102,'hesw'),
(103,'oldguo');

INSERT INTO course(cno,cname,tno)
VALUES
(1001,'linux',101),
(1002,'python',102),
(1003,'mysql',103);

INSERT INTO sc(sno,cno,score)
VALUES
(1,1001,80),
(1,1002,59),
(2,1002,90),
(2,1003,100),
(3,1001,99),
(3,1003,40),
(4,1001,79),
(4,1002,61),
(4,1003,99),
(5,1003,40),
(6,1001,89),
(6,1003,77),
(7,1001,67),
(7,1003,82),
(8,1001,70),
(9,1003,80),
(10,1003,96);

SELECT * FROM student;
SELECT * FROM teacher;
SELECT * FROM course;
SELECT * FROM sc;
===============
7.1 多表连接应用
-- 查询人口数量少于100人的城市信息
SELECT * FROM world.city WHERE population<100;
-- 延伸一下: 查询人口数量少于100人的城市名,人口数,国家名,国土面积
SELECT
city.name,
city.population,
country.name,
country.surfacearea
FROM city
JOIN country
ON city.countrycode=country.code
WHERE city.population<100;

说明:
1. 通过查询需求,找到所需表
2. 找到所有表之间的关联关系
语法:
两表关联:
from a join b on a.x=b.y
多表关联:
from a
join c on a.x=c.y
join b on c.z=b.z

例子:
-- 1. 每位老师讲的课程名称
SELECT teacher.tno,teacher.tname,GROUP_CONCAT(course.cname)
FROM teacher
JOIN course
ON teacher.tno=course.tno
GROUP BY teacher.tno;

思考: 如果老师名重名,或者老师讲多门课,怎么办?

-- 2. 每位学员学习了几门课?
SELECT student.sno,student.sname,COUNT(sc.cno)
FROM student
JOIN sc
ON student.sno=sc.sno
GROUP BY student.sno;

-- 3. 每位学员学习了几门课及课程名称列表?
SELECT
student.sno,
student.sname,
COUNT(sc.cno),
GROUP_CONCAT(course.cname)
FROM student
JOIN sc
ON student.sno=sc.sno
JOIN course
ON sc.cno=course.cno
GROUP BY student.sno;

张启
-- 5. 查询每位老师所教学生的人数及姓名
select teacher.tname,group_concat(student.sname),count(student.sname)
from teacher
join course
on teacher.tno = course.tno
join sc
on sc.cno = course.cno
join student
on student.sno = sc.sno
group by teacher.tno;

-- 6. 统计每位老师所教课程的平均分
select teacher.tname,group_concat(course.cname),avg(sc.score)
from teacher
join course
on teacher.tno = course.tno
join sc
on sc.cno = course.cno
group by teacher.tno;

王凯鹏:
-- 7. 统计每位老师所教课程不及格的学生名
select teacher.tname,group_concat(student.sname)
from teacher
join course
on teacher.tno = course.tno
join sc
on sc.cno = course.cno
join student
on student.sno = sc.sno
where sc.score < 60
group by teacher.tno;
-- 8. 查询平均成绩大于60分的同学的学号和平均成绩;
select student.sno, avg(sc.score)
from student
join sc
on student.sno = sc.sno
group by student.sno
having avg(sc.score) > 60;

陈娇娜 1
-- 9. 查询所有同学的学号、姓名、选课数、总成绩;
select student.sno,student.sname,count(course.cno),sum(sc.score)
from student join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by student.sno;

-- 10. 查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分

   select  course.cno,max(sc.score),min(sc.score)
   from course join sc on course.cno=sc.cno
   group by course.cno;

杨腾
-- 11. 查询每门课程被选修的学生数
select course.cname,count(student.sno)
from sc
on
jion couse
on
join student
group by course.cno

-- 12. 查询出只选修了一门课程的全部学生的学号和姓名
select student.sno,student.sname
from student
sc
group by sutdent.sno
having count(sc.cno)=1;

荆俊玮
-- 13. 查询选修课程门数超过1门的学生信息
select student.sno,student.sname,****
from student
sc
group by sutdent.sno
having count(sc.cno)>1
-- 15. 查询平均成绩大于85的所有学生的学号、姓名和平均成绩
select student.sno,student.sname,avg(sc.score)
from student
sc
group by sutdent.sno
having avg(sc.score)>85

扩展:
-- 16. -- 50
统计每门课程:
优秀(85分以上),
良好(70-85),
一般(60-70),
不及格(小于60)的学生列表
select 课程名 , 优秀 , 良好 , 一般 , 不及格

-- 17. -- 50 张现伟
统计各位老师,所教课程的及格率
select teacher.tno,course.cname,concat(count(case when sc.score>60 then 1 end)/count(sc.score)*100,"%") as "啊啊啊" from teacher join course on teacher.tno=course.tno join sc on course.cno=sc.cno group by teacher.tno,course.cno;

考试题:
https://www.jianshu.com/p/c99e2d3d295b
==============================================
写多表连接技巧

  1. 相关表
  2. 找相关表关联条件
    E-R 图 (自己扩展) ----> 开发DBA要做的事情

外连接
A left join B
A 表所有的数据+B表满足关联条件的数据

A right join B
B表所有的数据+A 满足关联条件的数据

实现外连接原生功能,需要把where的条件改为and/
mysql> select city.name,city.population ,country.name from city left join country on city.countrycode=country.code and city.population<100 order by population desc ;

结论: left join 应用场景,强制驱动表(关联查询中结果集小的)

  1. where 条件
  2. 原始表大小
  1. 别名的应用
    表别名: 给表设计的别名,在任何子句中调用
    列别名: 给select 后的列设定别名,在having 和 order by子句中调用

表别名:
select a.tname AS "老师姓名" ,group_concat(d.sname) AS "不及格的学生"
from teacher AS a
join course AS b
on a.tno = b.tno
join sc AS c
on c.cno = b.cno
join student AS d
on d.sno = c.sno
where c.score < 60
group by a.tno;

列别名:
select
student.sno AS 学生学号 ,
student.sname AS 学生姓名,
avg(sc.score) AS 平均成绩
from student
join sc
on student.sno=sc.sno
group by sutdent.sno
having 平均成绩 >85

==================
子查询 : (自己了解)
高级SQL编程: 内置函数,存储过程,函数,视图,事件,触发器,游标,Json开发 (自己了解)
==================

  1. show 语句
    show databases ; 查看所有库名
    show tables; 查看当前库下的所有表名.
    show tables from world; 查看world库下的所有表
    show create database world; 查看建库语句
    show create tables city; 查看建表语句
    show [global] variables like '%trx%'; 查看参数信息
    show grants for root@'localhost'; 查看用户权限信息
    show [full] processlist; 查看会话连接情况
    show engines; 查看当前数据库支持的引擎.
    show charset; 查看当前数据库支持的字符集.
    show collation; 查看当前数据库支持的排序规则.
    show [global] status; 查看当前数据库的状态信息.
    show status like '%lock%'\G 模糊查询数据库状态.
    show master status; 查看当前使用的二进制日志信息.
    show binary logs; 查看所有二进制日志信息.
    show binlog evnets in 'xxxx' 查看二进制日志事件信息.
    show relaylog events in 'xxx' 查看中继日志事件信息.
    show slave status \G 查看从库复制状态信息.
    show engine innodb status \G 查看InnoDB引擎相关状态信息.

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

  1. 元数据获取
    10.1 什么是元数据?
    库,表 : 属性(字符集,校对规则,数据类型,存储引擎,约束,其他数据)
    权限 :
    状态信息:
    等.

10.2 元数据获取方法
show语句 : 封装好的基础功能,可以实现大部分的元数据查询需求.
information_schema<视图>库: mysql 给我们定义好的元数据查询的方法.

10.3 information_schema<视图>库
应用场景: 做数据库资产统计.
tables :
TABLE_SCHEMA : 表所在的库
TABLE_NAME : 表名
ENGINE : 引擎
TABLE_ROWS : 表的行数
AVG_ROW_LENGTH: 平均行长度
INDEX_LENGTH : 索引长度
TABLE_COMMENT : 表的注释

例子:
-- 1. 统计所有库下的表的个数
select table_schema,count(table_name) from information_schema.tables group by table_schema;

-- 2. 统计不同存储引擎的表名
select engine,group_concat(table_name) from information_schema.tables group by engine;

-- 3. 统计所有非系统表,非InnoDB的表
mysql
information_schema
performace_schema
sys

SELECT table_schema,table_name ,ENGINE
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql','information_schema','performance_schema','sys')
HAVING ENGINE != 'innodb';

你可能感兴趣的:(数据库 4)