MySQL笔记(二)

4.設計範式

  • 第一範式

    數據庫中的每一個字段都是不可分割的原子值

    CREATE TABLE student(
        id INT PRIMARY KEY,
        name VARCHAR(20),
        address VARCHAR(20));
       
    INSERT INTO student VALUES(1,'A','中國陝西省延安市寶塔區');
    INSERT INTO student VALUES(2,'B','中國陝西省延安市安塞區');
    
    SELECT * FROM student;
    
    +----+------+-----------------------------------+
    | id | name | address                           |
    +----+------+-----------------------------------+
    |  1 | A    | 中國陝西省延安市寶塔區                |
    |  2 | B    | 中國陝西省延安市安塞區                |
    +----+------+-----------------------------------+
    
    上面的address換可以拆分,因此不滿足第一範式。
    那如何才滿足呢?
    
    CREATE TABLE student2 (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(20),
        country VARCHAR(20),
        province VARCHAR(20),
        city VARCHAR(20),
        details VARCHAR(20)
    );
    
    INSERT INTO student2 VALUES(1,'A','中國','陝西省','延安市','寶塔區');
    INSERT INTO student2 VALUES(2,'B','中國','陝西省','延安市','安賽區');
    
    SELECT * FROM student2;
    
    +----+------+---------+-----------+-----------+-----------+
    | id | name | country | province  | city      | details   |
    +----+------+---------+-----------+-----------+-----------+
    |  1 | A    | 中國    | 陝西省     | 延安市     | 寶塔區     |
    |  2 | B    | 中國    | 陝西省     | 延安市     | 安賽區     |
    +----+------+---------+-----------+-----------+-----------+
    
    該表對地址拆分的很詳細,便於後期可以直接根據countr或者province等字段進行操作。
    範式涉及的越詳細,對於某些操作可能更好,但不一定都好,要根據實際項目。
    
  • 第二範式

    第二範式必須滿足第一範式的前提。第二範式要求除主鍵的每一列,都必須完全依賴主鍵。

    一般在聯合主鍵下,容易出現不完全依賴的情況。

    CREATE TABLE myorder(
        product_id INT,
        customer_id INT,
        product_name VARCHAR(20),
        customer_name VARCHAR(20),
        PRIMARY KEY(product_id, customer_id);
    ); 
    
    該表是一個聯合主鍵的情況,product_name依賴於product_id,而customer_name依賴與customer_id,這樣就不滿足第二範式。
    
    如何才能滿足第二範式?可以對上表進行拆分!
    
    CREATE TABLE myorder(
        order_id INT PRIMARY KEY,
        product_id INT,
        customer_id INT
    );
    
    此表product_id與customer_id完全依賴於order_id
    
    CREATE TABLE product(
        id INT PRIMARY KEY,
        product_id INT
    );
    此表product_id依賴於id。
    
    CREATE TABLE customer(
        id INT PRIMARY KEY,
        customer_id INT
    );
    
    
  • 第三範式

    必須先滿足第二範式!除了主鍵列的其他列不能相互依賴

     customer_phone,也CREATE TABLE myorder(
        order_id INT PRIMARY KEY,
        product_id INT,
        customer_id INT,
        customer_phone VARCHAR(20)
    );
    從上表來看,通過customer_id也可以確定customer_phone,也就是說customer_id和customer_phone存在相互依賴關系。因此不滿足第三範式。
    
    還是可以通過拆分,讓其滿足第三範式。
    
     customer_phone,也CREATE TABLE myorder(
        order_id INT PRIMARY KEY,
        product_id INT,
        customer_id INT,
    );
    
    CREATE TABLE customer(
        id INT PRIMARY KEY,
        name INT,
        customer_phone VARCHAR(20)
    );
    
    

5.查詢

5.1 建立個表

新建一个查询用的数据库:selectTest
CREATE DATABASE selectTest;
选择该数据库:
USE selectTest;

建立學生表

学生表:
student
学号
姓名
性别
出生日期
所在班级

CREATE TABLE student(
    s_no VARCHAR(20) PRIMARY KEY COMMENT'学生学号',
    s_name VARCHAR(20) NOT NULL COMMENT'学生姓名 不能为空',
    s_sex VARCHAR(10) NOT NULL COMMENT'学生性别',
    s_birthday DATETIME COMMENT'学生生日',
    s_class VARCHAR(20) COMMENT'学生所在的班级'
);

建立教師表

teacher
教师编号
教师名字
教师性别
出生日期
职称
所在部门
CREATE TABLE teacher(
    t_no VARCHAR(20) PRIMARY KEY COMMENT'教师编号',
    t_name VARCHAR(20) NOT NULL COMMENT'教师姓名',
    t_sex VARCHAR(20) NOT NULL COMMENT'教师性别',
    t_birthday DATETIME COMMENT'教师生日',
    t_rof VARCHAR(20) NOT NULL COMMENT'教师职称',
    t_depart VARCHAR(20) NOT NULL COMMENT'教师所在的部门'
);

建立課程表

课程表:
course
课程号
课程课程名称
教师编号
CREATE TABLE course(
    c_no VARCHAR(20) PRIMARY KEY COMMENT'课程号',
    c_name VARCHAR(20) NOT NULL COMMENT'课程名称',
    t_no VARCHAR(20) NOT NULL COMMENT'教师编号 外键关联teacher表',
    FOREIGN KEY(t_no) references teacher(t_no)
);

建立成績表

srore
学号
课程号
成绩

CREATE TABLE score (
    s_no VARCHAR(20),
    c_no VARCHAR(20),
    sc_degree DECIMAL,
    foreign key(s_no) references student(s_no),
    foreign key(c_no) references course(c_no),
    PRIMARY KEY(s_no,c_no)
);

查看创建的表以及架构

SHOW TABLES;
+----------------------+
| Tables_in_selecttest |
+----------------------+
| course               |
| score                |
| student              |
| teacher              |
+----------------------+

查看student表结构    DESCRIBE student;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| s_no       | varchar(20) | NO   | PRI | NULL    |       |
| s_name     | varchar(20) | NO   |     | NULL    |       |
| s_sex      | varchar(10) | NO   |     | NULL    |       |
| s_birthday | datetime    | YES  |     | NULL    |       |
| s_class    | varchar(20) | YES  |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+

查看teacher表结构    DESCRIBE teacher;
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| t_no       | varchar(20) | NO   | PRI | NULL    |       |
| t_name     | varchar(20) | NO   |     | NULL    |       |
| t_sex      | varchar(20) | NO   |     | NULL    |       |
| t_birthday | datetime    | YES  |     | NULL    |       |
| t_rof      | varchar(20) | NO   |     | NULL    |       |
| t_depart   | varchar(20) | NO   |     | NULL    |       |
+------------+-------------+------+-----+---------+-------+

查看course表结构    DESCRIBE course;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| c_no   | varchar(20) | NO   | PRI | NULL    |       |
| c_name | varchar(20) | NO   |     | NULL    |       |
| t_no   | varchar(20) | NO   | MUL | NULL    |       |
+--------+-------------+------+-----+---------+-------+

查看score表结构    DESCRIBE score;
+-----------+---------------+------+-----+---------+-------+
| Field     | Type          | Null | Key | Default | Extra |
+-----------+---------------+------+-----+---------+-------+
| s_no      | varchar(20)   | NO   | PRI | NULL    |       |
| c_no      | varchar(20)   | NO   | MUL | NULL    |       |
| sc_degree | decimal(10,0) | YES  |     | NULL    |       |
+-----------+---------------+------+-----+---------+-------+

向表中添加数据

--学生表数据
INSERT INTO student VALUES('101','曾华','男','1977-09-01','95033');
INSERT INTO student VALUES('102','匡明','男','1975-10-02','95031');
INSERT INTO student VALUES('103','王丽','女','1976-01-23','95033');
INSERT INTO student VALUES('104','李军','男','1976-02-20','95033');
INSERT INTO student VALUES('105','王芳','女','1975-02-10','95031');
INSERT INTO student VALUES('106','陆军','男','1974-06-03','95031');
INSERT INTO student VALUES('107','王尼玛','男','1976-02-20','95033');
INSERT INTO student VALUES('108','张全蛋','男','1975-02-10','95031');
INSERT INTO student VALUES('109','赵铁柱','男','1974-06-03','95031');

--教师表数据
INSERT INTO teacher VALUES('804','李诚','男','1958-12-02','副教授','计算机系');
INSERT INTO teacher VALUES('856','张旭','男','1969-03-12','讲师','电子工程系');
INSERT INTO teacher VALUES('825','王萍','女','1972-05-05','助教','计算机系');
INSERT INTO teacher VALUES('831','刘冰','女','1977-08-14','助教','电子工程系');

--添加课程表
INSERT INTO course VALUES('3-105','计算机导论','825');
INSERT INTO course VALUES('3-245','操作系统','804');
INSERT INTO course VALUES('6-166','数字电路','856');
INSERT INTO course VALUES('9-888','高等数学','831');

--添加成绩表
INSERT INTO score VALUES('103','3-245','86');
INSERT INTO score VALUES('105','3-245','75');
INSERT INTO score VALUES('109','3-245','68');
INSERT INTO score VALUES('103','3-105','92');

INSERT INTO score VALUES('105','3-105','88');
INSERT INTO score VALUES('109','3-105','76');
INSERT INTO score VALUES('103','6-166','85');

INSERT INTO score VALUES('105','6-166','79');
INSERT INTO score VALUES('109','6-166','81');

數據呈現

student:
SELECT * FROM student;
+------+--------+-------+---------------------+---------+
| s_no | s_name | s_sex | s_birthday          | s_class |
+------+--------+-------+---------------------+---------+
| 101  | 曾华   | 男    | 1977-09-01 00:00:00 | 95033   |
| 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
| 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   |
| 104  | 李军   | 男    | 1976-02-20 00:00:00 | 95033   |
| 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
| 106  | 陆军   | 男    | 1974-06-03 00:00:00 | 95031   |
| 107  | 王尼玛 | 男    | 1976-02-20 00:00:00 | 95033   |
| 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
| 109  | 赵铁柱 | 男    | 1974-06-03 00:00:00 | 95031   |
+------+--------+-------+---------------------+---------+

teacher:
SELECT * FROM teacher;
+------+--------+-------+---------------------+--------+------------+
| t_no | t_name | t_sex | t_birthday          | t_rof  | t_depart   |
+------+--------+-------+---------------------+--------+------------+
| 804  | 李诚   | 男    | 1958-12-02 00:00:00 | 副教授 | 计算机系   |
| 825  | 王萍   | 女    | 1972-05-05 00:00:00 | 助教   | 计算机机系 |
| 831  | 刘冰   | 女    | 1977-08-14 00:00:00 | 助教   | 电子工程系 |
| 856  | 张旭   | 男    | 1969-03-12 00:00:00 | 讲师   | 电子工程系 |
+------+--------+-------+---------------------+--------+------------+

score:
SELECT * FROM score;
+------+-------+-----------+
| s_no | c_no  | sc_degree |
+------+-------+-----------+
| 103  | 3-105 |        92 |
| 103  | 3-245 |        86 |
| 103  | 6-166 |        85 |
| 105  | 3-105 |        88 |
| 105  | 3-245 |        75 |
| 105  | 6-166 |        79 |
| 109  | 3-105 |        76 |
| 109  | 3-245 |        68 |
| 109  | 6-166 |        81 |
+------+-------+-----------+

course:
SELECT * FROM course;
+-------+------------+------+
| c_no  | c_name     | t_no |
+-------+------------+------+
| 3-105 | 计算机导论 | 825  |
| 3-245 | 操作系统   | 804  |
| 6-166 | 数字电路   | 856  |
| 9-888 | 高等数学   | 831  |
+-------+------------+------+

5.2 查詢練習

  • 查询student表中所有的记录

    SELECT * FROM student;
    +------+--------+-------+---------------------+---------+
    | s_no | s_name | s_sex | s_birthday          | s_class |
    +------+--------+-------+---------------------+---------+
    | 1    | admin  | 男    | 1999-09-09 00:00:00 | 95033   |
    | 101  | 曾华   | 男    | 1977-09-01 00:00:00 | 95033   |
    | 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
    | 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   |
    | 104  | 李军   | 男    | 1976-02-20 00:00:00 | 95033   |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
    | 106  | 陆军   | 男    | 1974-06-03 00:00:00 | 95031   |
    | 107  | 王尼玛 | 男    | 1976-02-20 00:00:00 | 95033   |
    | 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
    | 109  | 赵铁柱 | 男    | 1974-06-03 00:00:00 | 95031   |
    +------+--------+-------+---------------------+---------+
    
  • 查询student表中所有记录的s_name,s_sex和s_class列

    SELECT s_no,s_name,s_class FROM  student;
    +------+--------+---------+
    | s_no | s_name | s_class |
    +------+--------+---------+
    | 1    | admin  | 95033   |
    | 101  | 曾华   | 95033   |
    | 102  | 匡明   | 95031   |
    | 103  | 王丽   | 95033   |
    | 104  | 李军   | 95033   |
    | 105  | 王芳   | 95031   |
    | 106  | 陆军   | 95031   |
    | 107  | 王尼玛 | 95033   |
    | 108  | 张全蛋 | 95031   |
    | 109  | 赵铁柱 | 95031   |
    +------+--------+---------+   
    
  • 查询教师所有的单位但是不重复的t_depart列

    去重用distinct

    SELECT distinct(t_depart) FROM teacher; 
    +------------+
    | t_depart   |
    +------------+
    | 计算机系   |
    | 计算机机系 |
    | 电子工程系 |
    +------------+
    
  • 查询score表中成绩在60-80之间所有的记录(sc_degree)

    SELECT * FROM score WHERE sc_degree BETWEEN 61 AND 79;  
    SELECT * FROM score WHERE sc_degree < 80 AND sc_degree > 60 ; 
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 105  | 3-245 |        75 |
    | 105  | 6-166 |        79 |
    | 109  | 3-105 |        76 |
    | 109  | 3-245 |        68 |
    +------+-------+-----------+
    
    注:between..and.. 默認閉區間
    
  • 查询score表中成绩为85, 86, 或者88的记录(sc_degree)

    在...之中的用IN

    SELECT * FROM score WHERE sc_degree IN(85, 86, 88);
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 3-245 |        86 |
    | 103  | 6-166 |        85 |
    | 105  | 3-105 |        88 |
    +------+-------+-----------+
    
  • 查询student表中'95031'班或者性别为'女'的同学记录

    或用OR語句

    SELECT * FROM student WHERE s_class = '95031' OR s_sex = '女';
    +------+--------+-------+---------------------+---------+
    | s_no | s_name | s_sex | s_birthday          | s_class |
    +------+--------+-------+---------------------+---------+
    | 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
    | 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
    | 106  | 陆军   | 男    | 1974-06-03 00:00:00 | 95031   |
    | 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
    | 109  | 赵铁柱 | 男    | 1974-06-03 00:00:00 | 95031   |
    +------+--------+-------+---------------------+---------+
    
  • 以class降序查询student表中所有的记录

    排序用ORDER BY語句,desc降序,asc升序。

    SELECT * FROM student ORDER BY s_class desc;  
    +------+--------+-------+---------------------+---------+
    | s_no | s_name | s_sex | s_birthday          | s_class |
    +------+--------+-------+---------------------+---------+
    | 1    | admin  | 男    | 1999-09-09 00:00:00 | 95033   |
    | 101  | 曾华   | 男    | 1977-09-01 00:00:00 | 95033   |
    | 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   |
    | 104  | 李军   | 男    | 1976-02-20 00:00:00 | 95033   |
    | 107  | 王尼玛 | 男    | 1976-02-20 00:00:00 | 95033   |
    | 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
    | 106  | 陆军   | 男    | 1974-06-03 00:00:00 | 95031   |
    | 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
    | 109  | 赵铁柱 | 男    | 1974-06-03 00:00:00 | 95031   |
    +------+--------+-------+---------------------+---------+
    
    
  • 以c_no升序.sc_degree降序score表中所有的数据

    意思是當默認按c_no升序排序,如果c_no相同,按照sc_degree降序

    排序用ORDER BY語句,desc降序,asc升序。

    SELECT * FROM score ORDER BY c_no ASC,sc_degree DESC;
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 3-105 |        92 |
    | 105  | 3-105 |        88 |
    | 109  | 3-105 |        76 |
    | 103  | 3-245 |        86 |
    | 105  | 3-245 |        75 |
    | 109  | 3-245 |        68 |
    | 103  | 6-166 |        85 |
    | 109  | 6-166 |        81 |
    | 105  | 6-166 |        79 |
    +------+-------+-----------+
    
  • 查询'95031'班的学生人数

    計數用count

    SELECT COUNT(s_class) FROM student WHERE s_class='95031';
    
    +----------------+
    | count(s_class) |
    +----------------+
    |              5 |
    +----------------+
    
  • 查询score表中的最高分数的学生号和课程号.(子查询或者排序)

    方法1:
    SELECT s_no,c_no FROM score WHERE sc_degree=(SELECT MAX(sc_degree) FROM score);
    
    +------+-------+
    | s_no | c_no  |
    +------+-------+
    | 103  | 3-105 |
    +------+-------+
    
    方法2:用排序法
    這種方法不能區別多個最高值的問題
    SELECT s_no,c_no FROM score ORDER BY sc_degree DESC LIMIT 0,1;
    LIMIT 0,1 表示從第0條記錄開始,一共選擇1條記錄。
    
  • 查询每门课的平均成绩

    平均成績是以課程爲單位計算的,因此需要根據課程號c_no來計算。

    最後希望展示出的結果是一個課程對應一個平均成績,因此select後面是c_no,AVG(sc_degree)

    AVG()是用來求平均值的

    SELECT c_no,AVG(sc_degree) FROM SCORE GROUP BY c_no;
    +-------+----------------+
    | c_no  | avg(sc_degree) |
    +-------+----------------+
    | 3-105 |        85.3333 |
    | 3-245 |        76.3333 |
    | 6-166 |        81.6667 |
    +-------+----------------+
    
  • 查询score表中至少有2名学生选修的,并且以3开头的课程的平均分

    對於復雜的查詢問題,可以將起拆解開來:
    
    1.查詢score表中學生的平均分
    
    SELECT c_no, AVG(sc_degree) FROM score GROUP BY c_no;
    
    2.每個課程的選擇人數要至少爲2,並且課程名字以3開頭
    
    having count(c_no)>=2
    
    c_no like '3%',用like來做匹配,'3%'表示開頭是3,%表示通配符,後面任意。
    
    綜上:
    
    SELECT c_no, AVG(sc_degree) FROM score GROUP BY c_no HAVING COUNT(c_no)>=2 and c_no LIKE '3%';
    
    +----------------+-------+
    | AVG(sc_degree) | c_no  |
    +----------------+-------+
    |        85.3333 | 3-105 |
    |        76.3333 | 3-245 |
    +----------------+-------+
    
  • 查询分数大于70但是小于90的s_no列

    方法1:
    SELECT s_no,sc_degree FROM score WHERE sc_degree>70 and sc_degree<90;
    或者
    SELECT  s_no,sc_degree FROM  score WHERE sc_degree BETWEEN 70 AND 90; 
    
    BETWEEN... AND...默認閉區間
    
    +------+-----------+
    | s_no | sc_degree |
    +------+-----------+
    | 103  |        86 |
    | 103  |        85 |
    | 105  |        88 |
    | 105  |        75 |
    | 105  |        79 |
    | 109  |        76 |
    | 109  |        81 |
    +------+-----------+
    
  • 查询所有的学生 s_name , c_no, sc_degree列

    s_name來自於表student,c_no, sc_degree來自於表score,這裏也涉及兩個表的關聯查詢。
    處理方法換是拆分,將單個表的情況列出來,在從中找對應關系
    
    SELECT s_no,s_name FROM student;
    +------+-----------+
    | s_no | s_name    |
    +------+-----------+
    | 101  | 曾华      |
    | 102  | 匡明      |
    | 103  | 王丽      |
    | 104  | 李军      |
    | 105  | 王芳      |
    | 106  | 陆军      |
    | 107  | 王尼玛    |
    | 108  | 张全蛋    |
    | 109  | 赵铁柱    |
    +------+-----------+
    
    SELECT s_no,c_no,sc_degree FROM score;
    
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 3-105 |        92 |
    | 103  | 3-245 |        86 |
    | 103  | 6-166 |        85 |
    | 105  | 3-105 |        88 |
    | 105  | 3-245 |        75 |
    | 105  | 6-166 |        79 |
    | 109  | 3-105 |        76 |
    | 109  | 3-245 |        68 |
    | 109  | 6-166 |        81 |
    +------+-------+-----------+
    
    可以發現,兩個表字都有s_no,可以根據s_no來匹配。
    
    SELECT s_name,c_no,sc_degree FROM student,score WHERE student.s_no=score.s_no;
    +-----------+-------+-----------+
    | s_name    | c_no  | sc_degree |
    +-----------+-------+-----------+
    | 王丽      | 3-105 |        92 |
    | 王丽      | 3-245 |        86 |
    | 王丽      | 6-166 |        85 |
    | 王芳      | 3-105 |        88 |
    | 王芳      | 3-245 |        75 |
    | 王芳      | 6-166 |        79 |
    | 赵铁柱    | 3-105 |        76 |
    | 赵铁柱    | 3-245 |        68 |
    | 赵铁柱    | 6-166 |        81 |
    +-----------+-------+-----------+
    
  • 查询所有学生的s_no, c_name, sc_degree列

    這裏也涉及兩個表的關聯查詢
     
    在course表中,有:c_no,c_name,t_no 
    在score表中,有:s_no,c_no,sc_degree
    
    可以發現兩個表中都有c_no,因此可以依據c_no來實現
    
    SELECT c_no,c_name FROM course;
    
    +-------+-----------------+
    | c_no  | c_name          |
    +-------+-----------------+
    | 3-105 | 计算机导论      |
    | 3-245 | 操作系统        |
    | 6-166 | 数字电路        |
    | 9-888 | 高等数学        |
    +-------+-----------------+
    
    SELECT c_no,s_no,sc_degree FROM score;
     
     +-------+------+-----------+
    | c_no  | s_no | sc_degree |
    +-------+------+-----------+
    | 3-105 | 103  |        92 |
    | 3-245 | 103  |        86 |
    | 6-166 | 103  |        85 |
    | 3-105 | 105  |        88 |
    | 3-245 | 105  |        75 |
    | 6-166 | 105  |        79 |
    | 3-105 | 109  |        76 |
    | 3-245 | 109  |        68 |
    | 6-166 | 109  |        81 |
    +-------+------+-----------+
    
    SELECT s_no,c_name, sc_degree FROM score,course WHERE score.c_no=course.c_no;
    
    +------+-----------------+-----------+
    | s_no | c_name          | sc_degree |
    +------+-----------------+-----------+
    | 103  | 计算机导论      |        92 |
    | 103  | 操作系统        |        86 |
    | 103  | 数字电路        |        85 |
    | 105  | 计算机导论      |        88 |
    | 105  | 操作系统        |        75 |
    | 105  | 数字电路        |        79 |
    | 109  | 计算机导论      |        76 |
    | 109  | 操作系统        |        68 |
    | 109  | 数字电路        |        81 |
    +------+-----------------+-----------+
    
  • 查询所有的学生 s_name , c_name, sc_degree列

    student中有 s_name,s_no
    course中有c_name,c_no
    score有s_no  c_no  sc_degree
    涉及三表關聯查詢,這裏就不能以一個字段作爲中間的關聯字段了,應該使用一個表作爲中間的關聯表
    
    SELECT s_name,c_name,sc_degree FROM student,course,score WHERE student.s_no=score.s_no AND course.c_no=score.c_no;
    
    +-----------+-----------------+-----------+
    | s_name    | c_name          | sc_degree |
    +-----------+-----------------+-----------+
    | 王丽      | 计算机导论      |        92 |
    | 王丽      | 操作系统        |        86 |
    | 王丽      | 数字电路        |        85 |
    | 王芳      | 计算机导论      |        88 |
    | 王芳      | 操作系统        |        75 |
    | 王芳      | 数字电路        |        79 |
    | 赵铁柱    | 计算机导论      |        76 |
    | 赵铁柱    | 操作系统        |        68 |
    | 赵铁柱    | 数字电路        |        81 |
    +-----------+-----------------+-----------+
    
    SELECT s_name,c_name,sc_degree FROM student,course,score WHERE student.s_no=score.s_no AND course.c_no=score.c_no;
    
  • 查询班级是'95031'班学生每门课的平均分

    select c_no,AVG(sc_degree) from score WHERE s_no IN (select s_no from student where s_class = '95031') GROUP BY c_no;
    
    select c_no,AVG(sc_degree) from score AS sc LEFT JOIN student AS s ON sc.s_no = s.s_no WHERE s.s_class = '95031' GROUP BY sc.c_no;
    
    SELECT sc.c_no,AVG(sc.sc_degree) FROM student AS s, score AS SC  WHERE s.s_class = '95031' AND s.s_no = sc.s_no GROUP BY sc.c_no ;
    +-------+-------------------+
    | c_no  | AVG(sc.sc_degree) |
    +-------+-------------------+
    | 3-105 |           82.0000 |
    | 3-245 |           71.5000 |
    | 6-166 |           80.0000 |
    +-------+-------------------+
    进阶,加入课程名称:
    SELECT sc.c_no, c.c_name, AVG(sc.sc_degree) FROM student AS s, score AS SC, course AS c  WHERE s.s_class = '95031' AND s.s_no = sc.s_no AND c.c_no = sc.c_no GROUP BY sc.c_no ;
    +-------+------------+-------------------+
    | c_no  | c_name     | AVG(sc.sc_degree) |
    +-------+------------+-------------------+
    | 3-105 | 计算机导论 |           82.0000 |
    | 3-245 | 操作系统   |           71.5000 |
    | 6-166 | 数字电路   |           80.0000 |
    +-------+------------+-------------------+
    
    
  • 查询选修"3-105"课程的成绩高于'109'号同学'3-105'成绩 的所有同学的记录

    SELECT * FROM student AS s, score AS sc WHERE sc.c_no = '3-105' AND sc.sc_degree > (SELECT sc_degree FROM score WHERE s_no = '109' AND c_no = '3-105') AND s.s_no = sc.s_no;
    
    
    +------+--------+-------+---------------------+---------+------+-------+-----------+
    | s_no | s_name | s_sex | s_birthday          | s_class | s_no | c_no  | sc_degree |
    +------+--------+-------+---------------------+---------+------+-------+-----------+
    | 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   | 103  | 3-105 |        92 |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   | 105  | 3-105 |        88 |
    +------+--------+-------+---------------------+---------+------+-------+-----------+
    
  • 查询成绩高于学号为'109',课程号为'3-105'的成绩的所有记录

    SELECT * FROM score WHERE sc_degree >(SELECT sc_degree FROM score WHERE s_no = '109' AND c_no = '3-105');
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 3-105 |        92 |
    | 103  | 3-245 |        86 |
    | 103  | 6-166 |        85 |
    | 105  | 3-105 |        88 |
    | 105  | 6-166 |        79 |
    | 109  | 6-166 |        81 |
    +------+-------+-----------+
    
    不过视频中仅仅查出来了score记录,但是并没有学生的信息,按照上面的来修改:
    SELECT * FROM student AS s, score AS sc WHERE sc.sc_degree > (SELECT sc_degree FROM score WHERE s_no = '109' AND c_no = '3-105') AND s.s_no = sc.s_no;
    
    还可以再进一步:
    SELECT s.s_no AS'学生学号', s.s_name AS'学生姓名', s_sex AS'性别', s_class AS'班级', c.c_no AS'课程编号', c.c_name AS'课程名称' ,sc.sc_degree AS'分数' FROM student AS s, score AS sc ,course AS c WHERE sc.sc_degree > (SELECT sc_degree FROM score WHERE s_no = '109' AND c_no = '3-105') AND s.s_no = sc.s_no AND sc.c_no = c.c_no;
    +----------+----------+------+-------+----------+------------+------+
    | 学生学号 | 学生姓名 | 性别 | 班级  | 课程编号 | 课程名称   | 分数 |
    +----------+----------+------+-------+----------+------------+------+
    | 103      | 王丽     | 女   | 95033 | 3-105    | 计算机导论 |   92 |
    | 103      | 王丽     | 女   | 95033 | 3-245    | 操作系统   |   86 |
    | 103      | 王丽     | 女   | 95033 | 6-166    | 数字电路   |   85 |
    | 105      | 王芳     | 女   | 95031 | 3-105    | 计算机导论 |   88 |
    | 105      | 王芳     | 女   | 95031 | 6-166    | 数字电路   |   79 |
    | 109      | 赵铁柱   | 男   | 95031 | 6-166    | 数字电路   |   81 |
    +----------+----------+------+-------+----------+------------+------+
    
  • 查询所有学号为108.101的同学同年出生的所有学生的s_no,s_name和s_birthday

    SELECT * FROM student WHERE YEAR(s_birthday) IN (SELECT YEAR(s_birthday) FROM student WHERE s_no IN('108','101'));
    +------+--------+-------+---------------------+---------+
    | s_no | s_name | s_sex | s_birthday          | s_class |
    +------+--------+-------+---------------------+---------+
    | 101  | 曾华   | 男    | 1977-09-01 00:00:00 | 95033   |
    | 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
    | 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
    +------+--------+-------+---------------------+---------+
    
  • 查询 张旭 教师任课的学生的成绩

    首先查一下張旭老師的編號
    SELECT t_no FROM teacher WHERE t_name='张旭';
    +------+
    | t_no |
    +------+
    | 856  |
    +------+
    
    再查一下張旭老師帶了那些課
    SELECT c_no FROM course WHERE t_no=(SELECT t_no FROM teacher WHERE t_name='张旭');
    +-------+
    | c_no  |
    +-------+
    | 6-166 |
    
    
    再查一下該課程對應的學生成績
    SELECT * FROM score where c_no=(SELECT c_no FROM course WHERE t_no=(SELECT t_no FROM teacher WHERE t_name='张旭'));
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 6-166 |        85 |
    | 105  | 6-166 |        79 |
    | 109  | 6-166 |        81 |
    +------+-------+-----------
    
  • 查询选修课程的同学人数多余 5 人的教师姓名

    插入一些數據便於操作
    INSERT INTO score VALUES('101','3-105','90');
    INSERT INTO score VALUES('102','3-105','91');
    INSERT INTO score VALUES('104','3-105','89');
    
    首先找出選修的課程人數大於5人的課程
    SELECT c_no  FROM  score GROUP BY c_no HAVING COUNT(*)>5;
    
    然後找出這個課程是由那個老師帶的
    select * from teacher;
    +------+--------+-------+------------+-----------+-----------------+
    | t_no | t_name | t_sex | t_birth    | t_rof     | t_dep           |
    +------+--------+-------+------------+-----------+-----------------+
    | 804  | 李诚   | 男    | 1958-12-02 | 副教授    | 计算机系        |
    | 825  | 王萍   | 女    | 1972-05-05 | 助教      | 计算机系        |
    | 831  | 刘冰   | 女    | 1977-08-14 | 助教      | 电子工程系      |
    | 856  | 张旭   | 男    | 1969-03-12 | 讲师      | 电子工程系      |
    +------+--------+-------+------------+-----------+-----------------+
    c_no無法直接與teacher中的字段關聯
    
    這裏利用一個course
    SELECT t_no FROM course WHERE c_no IN (SELECT c_no  FROM  score GROUP BY c_no HAVING COUNT(*)>5);
    
    +------+
    | t_no |
    +------+
    | 825  |
    +------+
    
    再找825課程對應的教師名字
    
    SELECT t_name FROM teacher WHERE t_no IN (SELECT t_no FROM course WHERE c_no IN (SELECT c_no  FROM  score GROUP BY c_no HAVING COUNT(*)>5));
    
    +--------+
    | t_name |
    +--------+
    | 王萍   |
    +--------+
    
  • 查询95033班和95031班全体学生的记录

    SELECT * FROM student WHERE s_class IN ('95033','95031') ORDER BY s_class;
    
    +------+--------+-------+---------------------+---------+
    | s_no | s_name | s_sex | s_birthday          | s_class |
    +------+--------+-------+---------------------+---------+
    | 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
    | 106  | 陆军   | 男    | 1974-06-03 00:00:00 | 95031   |
    | 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
    | 109  | 赵铁柱 | 男    | 1974-06-03 00:00:00 | 95031   |
    | 101  | 曾华   | 男    | 1977-09-01 00:00:00 | 95033   |
    | 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   |
    | 104  | 李军   | 男    | 1976-02-20 00:00:00 | 95033   |
    | 107  | 王尼玛 | 男    | 1976-02-20 00:00:00 | 95033   |
    +------+--------+-------+---------------------+---------+
    
    注:ORDER BY s_class 按照s_class從小到大的順序排列
    
  • 查询存在85分以上成绩的课程c_no

    SELECT * FROM score where sc_degree > 85;
    
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 101  | 3-105 |        90 |
    | 102  | 3-105 |        91 |
    | 103  | 3-105 |        92 |
    | 103  | 3-245 |        86 |
    | 104  | 3-105 |        89 |
    | 105  | 3-105 |        88 |
    +------+-------+-----------+
    
  • 查出所有'计算机系' 教师所教课程的成绩表

    SELECT * FROM score WHERE c_no IN (SELECT c_no FROM course WHERE t_no In (select t_no from teacher WHERE t_dep = '计算机系' ));
    
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 3-245 |        86 |
    | 105  | 3-245 |        75 |
    | 109  | 3-245 |        68 |
    | 101  | 3-105 |        90 |
    | 102  | 3-105 |        91 |
    | 103  | 3-105 |        92 |
    | 104  | 3-105 |        89 |
    | 105  | 3-105 |        88 |
    | 109  | 3-105 |        76 |
    +------+-------+-----------+
    
  • 查询'计算机系'与'电子工程系' 不同职称的教师的name和rof

    SELECT * FROM teacher WHERE t_depart = '计算机系' AND t_rof NOT IN (SELECT t_rof FROM teacher WHERE t_depart = '电子工程系')
    UNION
    SELECT * FROM teacher WHERE t_depart = '电子工程系' AND t_rof NOT IN (SELECT t_rof FROM teacher WHERE t_depart = '计算机系');
    
    +------+--------+-------+---------------------+--------+------------+
    | t_no | t_name | t_sex | t_birthday          | t_rof  | t_depart   |
    +------+--------+-------+---------------------+--------+------------+
    | 804  | 李诚   | 男    | 1958-12-02 00:00:00 | 副教授 | 计算机系   |
    | 856  | 张旭   | 男    | 1969-03-12 00:00:00 | 讲师   | 电子工程系 |
    +------+--------+-------+---------------------+--------+------------+
    
    注:UNION將兩個表拼接在了一起
    
  • 查询选修编号为"3-105"课程且成绩至少高于选修编号为'3-245'同学的記錄,并且按照sc_degree从高到地次序排序

    SELECT * FROM score WHERE sc_degree>ANY(SELECT sc_degree FROM score WHERE c_no='3-245')  AND c_no='3-105' ORDER BY sc_degree DESC;
    
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 103  | 3-105 |        92 |
    | 102  | 3-105 |        91 |
    | 101  | 3-105 |        90 |
    | 104  | 3-105 |        89 |
    | 105  | 3-105 |        88 |
    | 109  | 3-105 |        76 |
    +------+-------+-----------+
    
  • 查询选修编号为"3-105"且成绩高于选修编号为"3-245"课程的同学的記錄

    SELECT * FROM score WHERE sc_degree>All(SELECT sc_degree FROM score WHERE c_no='3-245')  AND c_no='3-105';
    
    +------+-------+-----------+
    | s_no | c_no  | sc_degree |
    +------+-------+-----------+
    | 101  | 3-105 |        90 |
    | 102  | 3-105 |        91 |
    | 103  | 3-105 |        92 |
    | 104  | 3-105 |        89 |
    | 105  | 3-105 |        88 |
    +------+-------+-----------+
    
  • 查询所有教师和同学的 name ,sex, birthday

    由於兩個表的字段可能不相同,聯合在一起後,注意新的表的字段要變化

    SELECT s_name AS name, s_sex AS sex, s_birthday AS birthday  FROM student WHERE s_sex = '女'
    UNION
    SELECT t_name AS name, t_sex AS sex, t_birthday AS birthday FROM teacher WHERE t_sex = '女';
    
  • 查询所有任课教师的t_name 和 t_depart(要在分数表中可以查得到)

    SELECT s_class FROM student WHERE s_sex = '男' GROUP BY s_class HAVING COUNT(s_no) > 1; 
    
  • 查询student 中每个学生的姓名和年龄(当前时间 - 出生年份

    SELECT s_name, YEAR(NOW()) - YEAR(s_birth) AS age FROM student;
    
    +-----------+------+
    | s_name    | age  |
    +-----------+------+
    | 曾华      |   43 |
    | 匡明      |   45 |
    | 王丽      |   44 |
    | 李军      |   44 |
    | 王芳      |   45 |
    | 陆军      |   46 |
    | 王尼玛    |   44 |
    | 张全蛋    |   45 |
    | 赵铁柱    |   46 |
    +-----------+------+
    
    注:1.如果 YEAR(NOW()) - YEAR(s_birth) 不用age表示的話,則輸出的就是
    +-----------+-----------------------------+
    | s_name    | YEAR(NOW()) - YEAR(s_birth) |
    +-----------+-----------------------------+
    | 曾华      |                          43 |
    | 匡明      |                          45 |
    | 王丽      |                          44 |
    | 李军      |                          44 |
    | 王芳      |                          45 |
    | 陆军      |                          46 |
    | 王尼玛    |                          44 |
    | 张全蛋    |                          45 |
    | 赵铁柱    |                          46 |
    +-----------+-----------------------------+
    2.NOW()表示現在的時間
    
  • 查询student中最大和最小的 s_birthday的值

    SELECT MAX(s_birthday),MIN(s_birthday) FROM student;
    +---------------------+---------------------+
    | MAX(s_birthday)     | MIN(s_birthday)     |
    +---------------------+---------------------+
    | 1977-09-01 00:00:00 | 1974-06-03 00:00:00 |
    +---------------------+---------------------+
    
  • 以班级号和年龄从大到小的顺序查询student表中的全部记录

    SELECt * FROM student ORDER BY s_class DESC, s_birthday; 
    +------+--------+-------+---------------------+---------+
    | s_no | s_name | s_sex | s_birthday          | s_class |
    +------+--------+-------+---------------------+---------+
    | 110  | 张飞   | 男    | 1974-06-03 00:00:00 | 95038   |
    | 103  | 王丽   | 女    | 1976-01-23 00:00:00 | 95033   |
    | 104  | 李军   | 男    | 1976-02-20 00:00:00 | 95033   |
    | 107  | 王尼玛 | 男    | 1976-02-20 00:00:00 | 95033   |
    | 101  | 曾华   | 男    | 1977-09-01 00:00:00 | 95033   |
    | 106  | 陆军   | 男    | 1974-06-03 00:00:00 | 95031   |
    | 109  | 赵铁柱 | 男    | 1974-06-03 00:00:00 | 95031   |
    | 105  | 王芳   | 女    | 1975-02-10 00:00:00 | 95031   |
    | 108  | 张全蛋 | 男    | 1975-02-10 00:00:00 | 95031   |
    | 102  | 匡明   | 男    | 1975-10-02 00:00:00 | 95031   |
    +------+--------+-------+---------------------+---------+
    
  • 查询"男"教师 及其所上的课

    SELECT * FROM course WHERE t_no IN (SELECT t_no FROM teacher WHERE t_sex = '男');
    +-------+----------+------+
    | c_no  | c_name   | t_no |
    +-------+----------+------+
    | 3-245 | 操作系统 | 804  |
    | 6-166 | 数字电路 | 856  |
    +-------+----------+------+
    
  • 查询最高分同学的s_no c_no 和 sc_degree;

    SELECT * FROM score WHERE sc_degree IN (SELECT MAX(sc_degree) FROM score);
    

6.事務

  • 什麼是事務

    在mysql中,事務是不可分割的最小工作單元,它保證了業務的完整性。

    例如:銀行轉賬

    a -> -100:
    
    update user set money=money-100 where name ='a';
    
    b -> +100:
    
    update user set money=money+100 where name ='b';
    

    在實際程序中,可能只有一條語句成功了,而另外一條沒有成功?就會出現前後不一致的情況。

    事務保證了業務的完整性,意思是保證要麼同時成成功,要麼同時失敗

  • 如何控制事務

    mysql默認自動提交

    select @@autocommit;
    +--------------+
    | @@autocommit |
    +--------------+
    |            1 |
    +--------------+
    

    自動提交的作用是當執行一個sql語句時,效果會立刻展現出來,且不能回滾

    例如:

    CREATE TABLE user1(
     id INT PRIMARY KEY,
     name VARCHAR(20),
     money INT
     );
     
     INSERT INTO user1VALUES(1,'a',1000);
     
     +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |  1000 |
    +----+------+-------+
    
    效果立刻顯現,此時我執行回滾操作:撤銷上一語句的效果
    
    rollback;
    
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |  1000 |
    +----+------+-------+
    1 row in set (0.00 sec)
    發現沒有改變
    
    如何才能改變呢?
    
    設置mysql自動提交爲false;
    
    set autocommit=0;
    
    +--------------+
    | @@autocommit |
    +--------------+
    |            0 |
    +--------------+
    
    這個時候就可以進行rollback的回滾操作。
    
    如果自動提交關閉,可以時候用手動提交的操作:commit;這個是才使用rollback是無效的
     
    也就是說事務提供了一個撤銷返回的機會
    
  • 手動開啓事務

    手動開始事務,除了set autocommit=0;還有2個方法:begin或者start transaction;

    事務開啓,就可以使用rollback;

    SELECT * FROM user1;
    
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   900 |
    |  2 | b    |  1100 |
    
    update user1 set money=money-100 where name ='a';
    update user1 set money=money-100 where name ='b';
    
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   800 |
    |  2 | b    |  1000 |
    +----+------+-------+
    
    rollback;
    
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   800 |
    |  2 | b    |  1000 |
    +----+------+-------+
    
    無效,是因此此時autocommit爲1,效果會立刻展示,不支持回滾。
    
    begin;(或者 start transaction)
    update user1 set money=money-100 where name ='a';
    update user1 set money=money+100 where name ='b';
    
    +----+------+-------+
    | id | name | money |
    +----+------+-------+
    |  1 | a    |   700 |
    |  2 | b    |  1100 |
    +----+------+-------+
    

    事務開啓之後,一旦commit,事務就已經結束了,就沒辦法回滾了。

  • 事務的特徵(ACID)

    A:原子性:事務是最小的單位,不可以在分割。

    C:一致性:要求同一事務中的sql語句,必須保證同時成功或者失敗

    I:隔離性:事務1和事務2是具有隔離

    D:持久性:事務一旦結束,就不返回。

​ 總結一下:

​ 事務開啓:1.set autocommit=0;2.begin;3.start transaction;

​ 提交:commit;

​ 回滾:rollback;

  • 隔離性

    隔離性有4種,包括:

    1.read uncommited; 讀未提交的

    2.read commited; 讀已提交的

    3.repeatable read; 可以重復讀

    4.serializable; 串行化

     查看隔離級別:
    
    A:系統級別:select@@global.tx_isolation;
    
    B:會話級別:select@@tx_isolation;
    +-----------------------+
    | @@global.tx_isolation |
    +-----------------------+
    | REPEATABLE-READ       |
    +-----------------------+
    1 row in set (0.00 sec)
    
    +-----------------+`
    | @@tx_isolation  |
    +-----------------+
    | REPEATABLE-READ |
    +-----------------+
    
    修改隔離級別:
    SET @@global.tx_isolation='Read-Committed'
    
    
    1.read uncommited
    有事務a和事務b,a對事務進行操作,在操作過程中,事務沒有被提交,但是b可以看到a的操作。這樣就容易出現賍讀的情況,也就是 1一個事務讀到了另外一個事務未提交的數據。
    
    2.read commited
    讀取提交的數據,容易出現問題,也就是如果數據發生改變,這讀取前後數據不一致,所以沒辦法重復讀
    
    3.repeatable read;  
    可以解決2的問題,容易出現幻讀的問題。事務A和事務B同時操作一張表,事務a提交的數據,不能被事務b讀取到,造成幻讀
    
    4.serializable;    串行化
    可以解決3的問題,兩邊操作按照串行的順序,事務A在操作的時候,事務b不能操作,直至事務a提交了。
    
    

7.參考

1.https://blog.csdn.net/weixin_42209572/article/details/98983741

2.https://www.bilibili.com/video/BV1Vt411z7wy?p=9

posted @ 2020-04-13 11:39  depth-perception  阅读(147)  评论(0)    收藏  举报