mysql-DBA

DQL——数据查询语言

2020-01-11  本文已影响0人  静如止水yw

1. select

select单独使用

mysql> select @@port;   查询端口
mysql> select @@datadir;   查询mysql的存放路径
mysql> select @@basedir;   查询mysql的安装路径
mysql> select @@innodb_flush_log_at_trx_commit;   查询参数
mysql> show variables like '%trx%';   相当于grep过滤
mysql> select database();  查询库名
mysql> select now();  查询系统时间
mysql> selete concat(user,"@",host) from mysql.user;  ##相当于sed替换 
SELECT 4*5;
SELECT SUM(xid) FROM student;

2. 配合其他字句使用

(1)子句列表介绍

FROM     -- 查询对象(表,视图)
WHERE    -- 过滤子句(grep)
GROUP BY -- 分组子句(统计分析类)
HAVING   -- 后过滤子句
ORDER BY -- 排序子句
LIMIT    -- 限制子句

(2)配合FROM应用

##英文单词介绍
-- city        -- 城市
-- id          --序号ID主键
-- NAME        --城市名
--Countrycode  -- 国家代码(CHA,USA)
-- Population  -- 城市人口数

##举例说明
1. 插叙表中所有数据
select * from city;
2. 查询name,population信息
select name,population from city;
#where配合等值查询
## 举例
1. 查询中国所有城市信息
select * from city where countrycode='CHN ';
2. 查询id为100的城市信息
select * from where id=100;
3. 查询中国河北省的城市信息
select * from city where countrycode='CHN' and district='hebei';
4. 查询中国或美国的城市
select * from city where  countrycode='CHN' or countrycode='USA';
或者 
select * from city where countrycode=('CHN','USA');
或者
select * from city where countrycode='CHN' union all select * from city where countrycode='USA';
#举例
1. 查询人口数量100w-200w之间的
select * from city where population >=1000000 and population <=2000000
或者
select * from city where population between 1000000 and 2000000;
2. 查询人口数量小于100人的城市
select * from city where population <100;
3. 查询国家代号是CH开头的城市信息
select * from city where countrycode like 'CH%';  ## %一般放在字符后面

(5)group_by分组子句+聚合函数应用

1. -- 执行过程:
   -- 排序
   -- 去重复
   -- 函数聚合
2. -- SQL_MODE(5.7+)=ONLY_FULL_GROUPBY
   
##聚合函数
count()     -- 计数
sum()       -- 求和
avg()       -- 求平均值
max()       -- 求最大值
min()       -- 最小值
group_concat()   -- 聚合列值

## 结果集显示特点:必须1v1,不能是1vn
##举例
1. 统计每个国家的人口总数
select countrycode,sum(population) from city group by countrycode;
2. 统计中国每个省的人口总数
select district,sum(population) from city where countrycode='CHN' group by district;
##金典错误##
mysql> SELECT name,district,SUM(population) FROM city WHERE countrycode='CHN' GROUP BY district;
        ERROR 1055 (42000): Expression \#1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'world.city.Name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with `sql_mode=only_full_group_by`
        原因: a. select后的列,不在 group by子句后
                 b. 也不在聚合函数中出现.
        修改: mysql> SELECT group_concat(name),district,SUM(population) FROM city WHERE countrycode='CHN' GROUP BY district;
3. 统计下中国每个省的城市个数及城市名
select countrycode,count(name) from city group by countrycode;

group_by是怎么用的
​       from——>where——>sum——>group_by
​       聚合函数不一定配合group_by,但group_by一定配合聚合函数。
##举例
统计中国每个省的人口总数,只显示总人口数大于500w的省的信息
select district,sum(population) from city where countrycode='CHN' group by district having sum(population)>=5000000 order by sum(population) desc;
##例子
1. 查询中国所有城市信息,人口数从小到大排序输出.
select * from city where countrycode='CHN' order by population desc;
2. 查询中国所有城市信息,按城市名排序
SELECT * FROM city 
WHERE countrycode='CHN' 
ORDER BY NAME;
3. 查询中国所有省的总人口,并按总人口数从大到小排序输出
SELECT district,SUM(population) FROM city 
WHERE countrycode='CHN' 
GROUP BY district 
ORDER BY SUM(population) DESC;
##例子
查询中国所有省的总人口,并按总人口数从大到小排序输出.
SELECT  district,SUM(population) FROM city 
WHERE countrycode='CHN' 
GROUP BY district 
ORDER BY SUM(population) DESC 
limit 5;   ##前5行

SELECT  district,SUM(population)  FROM  city
WHERE countrycode='CHN'
GROUP BY district
ORDER BY SUM(population) DESC
LIMIT 5 OFFSET 1;  ##跳过第一行(偏移一行)

SELECT  district,SUM(population)  FROM  city
WHERE countrycode='CHN'
GROUP BY district
ORDER BY SUM(population) DESC
LIMIT 10;   ##前十行

SELECT  district,SUM(population)  FROM  city
WHERE countrycode='CHN'
GROUP BY district
ORDER BY SUM(population) DESC
LIMIT 1,5;  ##2到6名,跳过第一行, 显示之后的5行
注意
LIMIT谨慎使用,如果超过500w+的表,使用时性能极差,一般会使用明确范围查找,使用between或者大于或小于等符号。

3. 多表连接的语法

(1)介绍
内连接:inner join

from a inner join b on A.x=B.y    -- 内连接的语法

外连接:left join right join

from A right join B on A.x=B.y

笛卡尔

from A join B

(2)作用
聚合多张表数据,实现查询需求
(3)多表连接示例

1. 查询人口数小于100人城市名,国家名,国土面积?
## 思路:找关联表,找关系列
select city.name country.name,countrycode.surfacearea,city.population from city join country on city.countrycode=countrycode.code where city.population <100;
2. 统计查询每位学员的平均分
select student.xid,student.xname,avg(score.score) from student join score on student.xid=score.xid group by student.xid,student.xname;
3. 统计每位学员学习了几门课
select student.xid,student.xname,count(score.score) from student join score on student.xid=score.xid group by student.xid,student.xname;
4. 查询每位老师教的课程名和价格
思路:teacher和course
select teacher.tname,course.cname,course.cprice from teacher join course on teacher.tid=course.tid;
5. 每位老师教的学生的个数和姓名列表
select teacher.tname,count(student.xid), group_concat(student.xname) from student join score on student.xid=score.xid join course on score.cid=course.cid join teacher on course.tid=teacher.tid group by teacher.tid,teacher.tname;

内连接综合练习题

1. 查询oldguo老师教的学生名
select concat (teacher.tname,'_',teacher.tid) as "教师名",group_concat(student.xname) as "学生列表" from student join score on student.xid=score.xid join course on score.cid=course.cid join teacher on course.tid=teacher.tid where teacher.tname='oldguo' group_by teacher.tid,teacher.tname;
2. 查询oldguo所教课程的平均分数
select concat (teacher.tname,'_',teacher.tid) as "教师名",course.cname as "课程名",avg(score.score) as "平均分" from teacher join course on teacher.tid=course.tid join score on course.cid=score.cid where teacher.tname='oldguo' group by teacher.tid,teacher.tname,course.cname;
3. 每位老师所教课程的平均分,并按平均分排序
select teacher.tname,count(student.xid),avg(score.score) from student join score on score.cid=course.cid join teacher on course.tid=teacher.tid group by teacher.tid,teacher.tname desc;
4. 查询白龙马,学习的课程名称有哪些?
select student.xname as "学生姓名",group_concat(course.cname) as "课程列表" from student join score on student.xid = score.xid join course on score.cid = course.cid where student.xname='白龙马' group by student.xid,student.xname;
5. 统计每位老师总收入
select teacher.tname,count(student.xid),sum(course.cprice) from teacher join course on teacher.tid = course.tid join score on course.cid = score.cid join student on score.xid = student.xid group by teacher.r=tid,teacher.tname
-- 5.1 统计每位老师,每门课程,分别的收入情况
SELECT 
CONCAT(teacher.`tname`,"_",teacher.`tid`) AS "讲师名",
course.`cprice`*COUNT(score.xid) AS "课程收入"
FROM teacher
JOIN course
ON teacher.`tid` = course.`tid`
JOIN score
ON course.`cid` = score.`cid`
GROUP BY teacher.`tid`,teacher.`tname` , course.`cid`;

-- 6. 统计每门课程学习的人数.
SELECT course.`cname`,COUNT(score.xid)
FROM course
JOIN score
ON course.`cid`=score.`cid`
GROUP BY course.`cname`;

-- 7. 查询oldboy老师教的学生不及格的学生名单 
SELECT 
CONCAT(teacher.tname,"_",teacher.tid) AS "教师名",
GROUP_CONCAT(CONCAT(student.xname,":",score.score))
FROM teacher
JOIN course
ON teacher.`tid`=course.`tid`
JOIN score
ON course.`cid`=score.`cid`  
JOIN student 
ON score.`xid`=student.`xid`
WHERE score.`score`<60
GROUP BY teacher.tid,teacher.tname;

-- 8. 统计每位老师不及格学生名单 
SELECT 
CONCAT(teacher.tname,"_",teacher.tid) AS "教师名"
,GROUP_CONCAT(CONCAT(student.xname,":",score.score))
FROM teacher
JOIN course
ON teacher.`tid`=course.`tid`
JOIN score
ON course.`cid`=score.`cid`  
JOIN student 
ON score.`xid`=student.`xid`
WHERE score.`score`<60
GROUP BY teacher.tid,teacher.tname;

-- 9. 每位老师所教课程的平均分,并按平均分排序.
SELECT 
CONCAT(teacher.tname,"_",teacher.tid) AS "教师名",
course.`cname`,
AVG(score.`score`)
FROM teacher
JOIN course
ON teacher.`tid`=course.`tid`
JOIN score
ON course.`cid`=score.`cid`  
GROUP BY teacher.tid,teacher.tname,course.`cid`;

-- 10. 查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分.
SELECT course.`cid`,MAX(score.`score`),MIN(score.`score`)
FROM course
JOIN score
ON course.`cid`=score.`cid` 
GROUP BY course.`cid`;

-- 11. 查询平均成绩大于60分的同学的学号和平均成绩.
SELECT 
CONCAT(student.`xname`,"_",student.`xid`),
AVG(score.`score`)
FROM student
JOIN score
ON student.`xid`=score.`xid`
GROUP BY student.`xname`,student.`xid`
HAVING AVG(score.`score`)>60
ORDER BY AVG(score.`score`) DESC ;

扩展:
-- 12. 统计各位老师,所教课程的及格率
SELECT 
CONCAT(teacher.tname,"_",teacher.tid) AS "教师名",
course.`cname`,
CONCAT(COUNT(CASE WHEN score.score>60 THEN 1  END)/COUNT(score.xid)*100,"%")
FROM teacher
JOIN course
ON teacher.`tid`=course.`tid`
JOIN score
ON course.`cid`=score.`cid`  
GROUP BY teacher.tid,teacher.tname,course.`cid`;

-- 13. 统计每门课程:优秀(85分以上),良好(70-85),一般(60-70),不及格(小于60)的学生列表
SELECT 
course.`cname` AS 课程名称,
GROUP_CONCAT(CASE WHEN score.`score` >= 85 THEN student.xname END )  AS "优秀",
GROUP_CONCAT(CASE WHEN score.`score` >=70 AND score.`score` < 85  THEN student.xname  END) AS "良好",
GROUP_CONCAT(CASE WHEN score.`score` >=60  AND score.`score` <70 THEN  student.xname  END  )AS "一般",
GROUP_CONCAT(CASE WHEN score.`score` <60  THEN  student.xname END  ) AS "不及格"
FROM student 
JOIN score
ON student.xid = score.xid 
JOIN course 
ON score.`cid`=course.`cid`
GROUP BY course.`cid`;

as  -- 表示别名关键字

left/right join 外连接应用

一般应用在强制驱动表时,强制小结果集驱动大表。
① 生产中可以使用left join 强制驱动表,尽量减少next loop的出现
② 为什么要强制?inner join 优化器,自动选择,按照索引选择的几率较大

别名的应用

(1)列别名
SELECT 
course.cname AS 课程名称,
GROUP_CONCAT(CASE WHEN score.score >= 85 THEN student.xname END )  AS "优秀",
GROUP_CONCAT(CASE WHEN score.score >=70 AND score.score < 85  THEN student.xname  END) AS "良好",
GROUP_CONCAT(CASE WHEN score.score >=60  AND score.score <70 THEN  student.xname  END  )AS "一般",
GROUP_CONCAT(CASE WHEN score.score <60  THEN  student.xname END  ) AS "不及格"
FROM student 
JOIN score
ON student.xid = score.xid 
JOIN course 
ON score.cid=course.cid
GROUP BY course.cid;
说明:  1. 为了显示的好看.  2. 可以在 having 或 order by 子句中调用

(2)表别名

SELECT 
CONCAT(te.tname,"_",te.tid) AS "教师名",
GROUP_CONCAT(CONCAT(st.xname,":",sc.score))
FROM teacher as te 
JOIN course as  co 
ON te.tid=co.tid
JOIN score as sc 
ON co.cid=sc.cid 
JOIN student  as st
ON sc.xid=st.xid
WHERE sc.score<60
GROUP BY te.tid,te.tname;

SELECT 
CONCAT(te.tname,"_",te.tid) AS "教师名",
GROUP_CONCAT(CONCAT(st.xname,":",sc.score))
FROM teacher AS te 
JOIN course AS  co 
ON te.tid=co.tid
JOIN score AS sc 
ON co.cid=sc.cid 
JOIN student  AS st
ON sc.xid=st.xid
WHERE sc.score<60
GROUP BY te.tid,te.tname;

show语句的应用

——查看所有库
show databases;
——查看当前库下的所有表
show tables;
show tables from world;
——查看当前并发会话信息
show processlist;
show full processlist;
——查看数据库支持的权限
show privileges;
——查看数据库参数信息
show variables
show variables like '%trx%';
——查看字符集&校对规则
show charset;
show collation;
——查看建库&建表语句
show create database world;
show create table world.city;
——查看用户权限
show grants for root@'localhost';
——查看支持的存储引擎
show engines;
——查询表中索引信息
show index from world.city;
——查看数据库当前状态信息
show status;
show status like '%lock%';
——查看InnoDB引擎相关的状态信息(内存,事务,锁,线程……)
show engine innodb status\G;
——查看二进制日志相关信息
show binary logs;
show master status;
show binlog events in 'xxxx';
——查看主从复制相关信息  show relaylog events in 'xxxx';
show slave status \G
——查看show相关的所有命令
mysql> help show ;

4.统计信息库(information_schema)

视图的介绍:
​ ① 安全:只允许查询,不知道操作的是什么对象。
​ ② 方便:只需要简单的select语句即可使用。
information_schema的作用:
​ ① 方便做数据库资产统计(库\表:个数;数据量;核心业务表的数据行的变化[大小,行数];每张表的数据字典信息).
​ ② 获取到Server层状态信息.
​ ③ 获取到InnoDB引擎层的状态信息.
应用举例:

TABLES : 
TABLE_SCHEMA        : 表所在的库 
TABLE_NAME            : 表名
ENGINE                      : 表的引擎   
TABLE_ROWS            : 表的行数
AVG_ROW_LENGTH : 平均行长度(字节) 
INDEX_LENGTH        : 索引占用长度(字节) 
TABLE_COMMENT    : 表注释 

-- 1. 简单查询体验TABLES信息
SELECT * FROM TABLES;

-- 2. 所有业务库和表的名字.
SELECT table_schema , table_name 
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql');

-- 3. 统计每个业务库,表的个数和列表
SELECT table_schema , COUNT(table_name),GROUP_CONCAT(table_name) 
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql')
GROUP BY table_schema;

-- 4. 统计业务数据库的总数据量
SELECT SUM(table_rows * AVG_ROW_LENGTH+index_length)/1024 AS total_KB
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql');

-- 5. 每个业务库分别统计数据量
SELECT table_schema,SUM(table_rows * AVG_ROW_LENGTH+index_length)/1024 AS total_KB
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql')
GROUP BY table_schema
ORDER  BY total_KB DESC ;

-- 6. top 3 数据量大的表
SELECT table_schema,table_name,(table_rows * AVG_ROW_LENGTH+index_length)/1024 AS table_kb
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql')
ORDER BY  table_kb DESC 
LIMIT 3;

-- 运维需求
-- 7. 查询所有非INNODB的表
SELECT table_schema,table_name ,ENGINE FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql')
AND ENGINE <> 'innodb';

-- 8. 查询所有非INNODB的表 , 并且提出修改建议
SELECT 
table_schema,
table_name ,
ENGINE ,
CONCAT("alter table ",table_schema,".",table_name," engine=innodb;") AS "修改建议"
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql')
AND ENGINE <> 'innodb';

-- 9. 所有业务库和表的名字,并且生成备份语句.
SELECT 
table_schema , 
table_name ,
CONCAT("mysqldump ",table_schema," ",table_name," > /bak/",table_schema,"_",table_name,".sql") AS "备份"
FROM information_schema.tables
WHERE table_schema NOT IN ('sys','information_schema','performance_schema','mysql');

-- 10. 统计 数据库所有业务表的字典信息
mysql> select table_schema,
table_name,column_name ,data_type,Column_key ,COLUMN_COMMENT 
from columns 
WHERE table_schema 
NOT IN ('sys','informatiion_schema','performance_schema','mysql');
上一篇下一篇

猜你喜欢

热点阅读