zoukankan      html  css  js  c++  java
  • Mysql-SQL基础应用02 DQL-Select 多表连接

    DQL-Select 多表连接

    1.1连接方式

    a.笛卡尔乘积

    mysql> select * from a,b;
    

    b.内连接

    mysql> select * from a join b on a.id=b.aid;
    

    c.外连接

    mysql> select * from a left join b on a.id=b.aid;
    mysql> select * from a right  join b on a.id=b.aid;
    mysql> select * from a left join b on a.id=b.aid and  b.aid is null;
    

    1.2 列子

    1.2.1 前提条件

    student :学生表
    sno: 学号
    sname:学生姓名
    sage: 学生年龄
    ssex: 学生性别
    
    teacher :教师表
    tno: 教师编号
    tname:教师名字
    
    course :课程表
    cno: 课程编号
    cname:课程名字
    tno: 教师编号
    
    score :成绩表
    sno: 学号
    cno: 课程编号
    score:成绩
    
    项目构建
    mysql> create database school charset utf8mb4;
    
    mysql> use school
    
    
    mysql> source /root/school.sql
    Database changed
    Query OK, 0 rows affected (0.02 sec)
    
    Query OK, 0 rows affected (0.01 sec)
    
    Query OK, 0 rows affected (0.01 sec)
    
    Query OK, 0 rows affected (0.00 sec)
    
    Query OK, 10 rows affected (0.03 sec)
    Records: 10  Duplicates: 0  Warnings: 0
    
    Query OK, 4 rows affected (0.00 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    Query OK, 4 rows affected (0.00 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    
    Query OK, 17 rows affected (0.01 sec)
    Records: 17  Duplicates: 0  Warnings: 0
    ############################/root/school.sql#############################
    [root@oldboy ~]# cat school.sql 
    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'),
    (104,'alex');
    
    INSERT INTO course(cno,cname,tno)
    VALUES
    (1001,'linux',101),
    (1002,'python',102),
    (1003,'mysql',103),
    (1004,'go',105);
    
    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);
    
    

    1.2.2 大显身手

    #############################################################
     核心思路: 
    	 1.找到所有相关表 
    	 2.找到所有表之间的关联关系
    	 3.罗列其他的查询条件
    #############################################################
    
    -- 统计下每个学生平均成绩 
    
    -- a.分析题意,找出所有相关表 
    student
    sc
    
    -- b. 找到以上表的直接或间接关联条件
    student.sno
    sc.sno
    
    -- c. 列举你要查询的列条件 
    student.sname  
    sc.score 
    
    -- d. 组合 
    
    mysql> select student.sname,avg(sc.score) 
    from student join sc on student.sno = sc.sno 
    group by student.sno;
    
    
    -- 练习 : 
    -- 1.  每位学生学习的课程门数
    
    SELECT student.sname,COUNT(sc.score)
    FROM student JOIN sc  ON student.sno=sc.sno 
    GROUP BY student.sno;
    
    
    -- 2.  每位老师所教的课程门数
    
    SELECT teacher.tname ,COUNT(course.cname)
    FROM teacher JOIN course
    ON teacher.tno=course.tno
    GROUP BY teacher.tno;
    
    -- 3.  每位老师所教的课程门数和名称
    
    SELECT teacher.tname ,COUNT(course.cname),GROUP_CONCAT(course.cname)
    FROM teacher JOIN course
    ON teacher.tno=course.tno
    GROUP BY teacher.tno;
    
    -- 4.  每位学生学习的课程门数和名称
    SELECT student.sname,COUNT(sc.score),GROUP_CONCAT(course.cname)
    FROM student
    JOIN sc 
    ON student.sno=sc.sno
    JOIN course
    ON sc.cno=course.cno
    GROUP BY student.sno;
    
    
    
    
    -- 多表SQL练习题
    -- 1. 统计zhang3,学习了几门课
    
    SELECT student.sname ,COUNT(*) 
    FROM student 
    JOIN sc 
    ON student.sno=sc.sno
    WHERE student.sname='zhang3';
    
    -- 2. 查询zhang3,学习的课程名称有哪些?
    
    SELECT student.sname ,GROUP_CONCAT(course.cname)
    FROM student 
    JOIN sc 
    ON student.sno=sc.sno
    JOIN course
    ON sc.cno=course.cno
    WHERE student.sname='zhang3'
    GROUP BY student.sname
    
    -- 3. 查询oldguo老师教的学生名.
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher
    JOIN course
    ON teacher.tno=course.tno
    JOIN sc 
    ON course.cno=sc.cno
    JOIN student
    ON sc.sno=student.sno
    WHERE teacher.tname='oldguo'
    GROUP BY teacher.tno
    
    -- 4. 查询oldguo所教课程的平均分数
    
    SELECT teacher.tname,AVG(sc.score) 
    FROM teacher 
    JOIN course
    ON teacher.tno=course.tno
    JOIN sc 
    ON course.cno=sc.cno
    WHERE teacher.tname='oldguo'
    GROUP BY teacher.tno;
    
    -- 5. 每位老师所教课程的平均分,并按平均分排序
    
    SELECT teacher.tname,course.cname,AVG(sc.score) 
    FROM teacher 
    JOIN course
    ON teacher.tno=course.tno
    JOIN sc 
    ON course.cno=sc.cno
    GROUP BY teacher.tno , course.cno
    ORDER BY AVG(sc.score) DESC;
    
    
    -- 6. 查询oldguo所教的不及格的学生姓名
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher
    JOIN course
    ON teacher.tno=course.tno
    JOIN sc 
    ON course.cno=sc.cno
    JOIN student
    ON sc.sno=student.sno
    WHERE teacher.tname='oldguo' AND sc.score<60
    GROUP BY teacher.tno
    
    
    -- 7. 查询所有老师所教学生不及格的信息
    SELECT teacher.tname,GROUP_CONCAT(student.sname)
    FROM teacher
    JOIN course
    ON teacher.tno=course.tno
    JOIN sc 
    ON course.cno=sc.cno
    JOIN student
    ON sc.sno=student.sno
    WHERE  sc.score<60
    GROUP BY teacher.tno
    
    -- 8. 查询平均成绩大于60分的同学的学号和平均成绩;
    SELECT student.sno,student.sname,AVG(sc.score)
    FROM student
    JOIN sc 
    ON student.sno=sc.sno
    GROUP BY student.sno
    HAVING AVG(sc.score)>60
    
    -- 9. 查询所有同学的学号、姓名、选课数、总成绩;
    SELECT student.sno ,student.sname,COUNT(*),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(sc.sno)
    FROM course
    JOIN sc 
    ON course.cno=sc.cno
    GROUP BY course.cno 
    
    -- 12.查询出只选修了一门课程的全部学生的学号和姓名
    SELECT course.cname,GROUP_CONCAT(CONCAT(student.sno,":",student.sname))
    FROM course 
    JOIN sc
    ON course.cno=sc.cno 
    JOIN student
    ON sc.sno=student.sno
    GROUP BY course.cno
    
    -- 13.查询选修课程门数超过1门的学生信息
    SELECT student.sname,COUNT(*)
    FROM student
    JOIN sc
    ON student.sno=sc.sno
    GROUP BY student.sno
    HAVING COUNT(*)>1
    
    -- 14.查询平均成绩大于85的所有学生的学号、姓名和平均成绩 
    SELECT student.sno,student.sname,AVG(sc.score)
    FROM student
    JOIN sc 
    ON student.sno=sc.sno
    GROUP BY student.sno
    HAVING AVG(sc.score)>85
    -- 15.统计各位老师,所教课程的及格率
    
    SELECT teacher.tname,COUNT(CASE  WHEN sc.score>=60 THEN 1 END)/COUNT(*)
    FROM teacher
    JOIN course
    ON teacher.tno=course.tno
    JOIN sc
    ON course.cno=sc.cno
    GROUP BY teacher.tno
    
    -- 16.统计每门课程:优秀(85分以上),良好(70-85),一般(60-70),不及格(小于60)的学生列表
    
    SELECT 
    course.cname,
    GROUP_CONCAT(CASE WHEN sc.score>=85  THEN student.sname END) AS 优秀,
    GROUP_CONCAT(CASE WHEN sc.score>=70 AND sc.score<85  THEN student.sname END) AS 良好,
    GROUP_CONCAT(CASE WHEN sc.score>=60 AND sc.score<70  THEN student.sname END) AS 一般,
    GROUP_CONCAT(CASE WHEN sc.score<60  THEN student.sname END) AS 差
    FROM course
    JOIN sc 
    ON course.cno=sc.cno
    JOIN student
    ON sc.sno=student.sno
    GROUP BY course.cno
    

    2.元数据获取

    2.1 show

    mysql> show databases;
    mysql> show tables;
    mysql> show privileges;
    mysql> show grants for root@'localhost';
    mysql> show create database  school;
    mysql> show charset ;
    mysql> show collation;
    mysql> show variables like '%char%';
    mysql> show status like '%binglog%'
    mysql> show processlist;
    mysql> show index from school.student;
    mysql> show engines;
    mysql> show binlog events ;
    mysql> show master status ;
    mysql> show slave status ;
    mysql> show slave hosts;
    mysql> show plugins;
    mysql> show engine innodb status ;
    mysql> show relaylog events;
    mysql> show open tables;
    
    

    3 information_schema

    3.1.1介绍

    视图. 查询元数据的方法
    

    3.2.1 tables视图介绍

    TABLE_SCHEMA 表所在库
    TABLE_NAME 表名
    ENGINE 存储引擎
    TABLE_ROWS 表的行数(粗略统计)
    AVG_ROW_LENGTH 平均行长度(粗略统计)
    INDEX_LENGTH 索引长度(粗略统计)
    DATA_FREE 碎片数
    TABLE_COMMENT 表注释
    

    3.2.2 tables视图应用例子:

    1. 统计所有库,对应的表个数和名字列表
    mysql> select table_schema,count(*),group_concat(table_name)
        -> from information_schema.tables
        -> group by table_schema;
    | world              |        3 | countrylanguage,country,city 
    
    2. 统计每个库的数据量大小
    mysql> select table_schema,sum(table_rows*avg_row_length+index_length)/1024
        -> from information_schema.tables
        -> group by table_schema;
    +--------------------+--------------------------------------------------+
    | table_schema       | sum(table_rows*avg_row_length+index_length)/1024 |
    +--------------------+--------------------------------------------------+
    | information_schema |                                             NULL |
    | mysql              |                                        2338.7188 |
    | performance_schema |                                           0.0000 |
    | school             |                                          63.9834 |
    | sys                |                                          15.9961 |
    | test               |                                          16.0000 |
    | world              |                                         781.9990 |
    +--------------------+--------------------------------------------------+
    
    
    3. 拼接语句 
    a. 查询一下业务数据库中,非InnoDB的表
    mysql> SELECT  table_schema , table_name ,engine FROM information_schema.tables 
        -> WHERE 
        -> table_schema NOT IN ('mysql','sys','information_schema','performance_schema') 
        -> AND ENGINE <>'innodb';   
    b.将非InnoDB表批量替换为InnoDB
    SELECT  concat("alter table ",table_schema,".",table_name," engine=innodb;") FROM information_schema.tables 
    WHERE 
    table_schema NOT IN ('mysql','sys','information_schema','performance_schema','world') 
    AND ENGINE <>'innodb' into outfile '/tmp/alter.sql' ;
    mysqldump -uroot -p123 world city >/databak/world_city.sql
    
    SELECT  concat("mysqldump -uroot -p123 ",table_schema," ",table_name," >/databak/",table_schema,"_",table_name,".sql") FROM information_schema.tables 
    WHERE 
    table_schema NOT IN ('mysql','sys','information_schema','performance_schema') into outfile '/tmp/bak.sh' ;
    

    3.2.3 columns

    TABLE_SCHEMA
    TABLE_NAME
    COLUMN_NAME
    DATA_TYPE
    COLUMN_KEY
    COLUMN_COMMENT
    
    select table_schema,table_name ,column_name from information_schema.columns
    where table_schema NOT IN ('mysql','sys','information_schema','performance_schema');
    
  • 相关阅读:
    C语言学习11(循环结构:for语句)
    C语言学习9(循环结构:while语句)
    C语言学习8(选择结构的嵌套)
    C语言学习笔记2
    C语言学习笔记1
    C语言的学习5(数据的输出)
    C语言学习12(函数的定义)
    第二十一章流 14临时文件 简单
    第二十一章流 12输出数据到文件指定位置处seekp() 简单
    第二十一章流 11指定读取文件中的数据seekg() 简单
  • 原文地址:https://www.cnblogs.com/lailaoban/p/14768067.html
Copyright © 2011-2022 走看看