4. MySQL 多表查询

重点:

MySQL 的 三种安装方式:包安装,二进制安装,源码编译安装。

MySQL 的 基本使用

MySQL 多实例

DDLcreate alter drop

DML insert update delete

DQL select

3.5)DDL 语句

表:二维关系

设计表:遵循规范

定义:字段,索引

字段:字段名,字段数据类型,修饰符

约束,索引:应该创建在经常用作查询条件的字段上

3.5.1) 创建表

参考文档: MySQL :: MySQL 8.0 Reference Manual :: 13.1.20 CREATE TABLE Statement

// 创建表

CREATE TABLE


// 获取帮助

HELP CREATE TABLE

外键管理参考文档:MySQL :: MySQL 8.0 Reference Manual :: 13.1.20.5 FOREIGN KEY Constraints

创建表的方法

(1)直接创建

CREATE TABLE [IF NOT EXISTS] 'tbl_name' (col1 type1 修饰符, col2 type2 修饰符, ...)


// 字段信息

col type1

PRIMARY KEY(col1,...)

INDEX(col1, ...)

UNIQUE KEY(col1, ...)


// 表选项:

ENGINE [=] engine_name

ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT}

注意:

Storage Engine 是指表类型,也即在表创建时指明其使用的存储引擎

同一库中不同表可以使用不同的存储引擎

同一个库中表建议要使用同一种存储引擎类型

范例: 创建表

创建一个名为 student 的数据表

定义一个名为 id 的字段

SMALLINT整数数据类型 最大值 65535

UNSIGNED仅存储正 整数

PRIMARY KEY表的主 键,每个 主键值都 必须是唯一且不为空。

AUTO_INCREMENT值会 自动递增

定义一个名为 name 的字段

VARCHAR(10)字符串类型 存储的 最大字符数为 1 0。

NOT NULL 不允许存储空值

定义一个名为 age 的字段

TINYINT整数数据类型最 大值 255

UNSIGNED仅存储正 整数

创建一个名为 gender 的字段

ENUM('M','F')数据类型 为 ENUM 枚举类型

DEFAULT 'M'默认值将 被设置 为 'M'

创建表的 SQL 语句的结尾部分

ENGINE=InnoDB指定存 储引擎为 I nnoDB

UTO_INCREMENT=10指定 自增列的初始值为 10。这表示在向具有自增功能的列中插入新行时,首个自增值将为 10,接 下来的自增值将逐次增加 1。

EFAULT CHARSET=utf8指 定表的默认字符集为 utf8。( 不默认使用数据库的默认字符集 )

CREATE TABLE student (

id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,

name VARCHAR(10) NOT NULL,

age TINYINT UNSIGNED,

gender ENUM('M','F') DEFAULT 'M'

)ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

// 创建数据库

MariaDB [(none)]> create database db1;

Query OK, 1 row affected (0.00 sec)


// 进入数据库

MariaDB [(none)]> use db1;

Database changed


// 创建数据表

MariaDB [db1]> CREATE TABLE student (

    -> id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,

    -> name VARCHAR(10) NOT NULL,

    -> age TINYINT UNSIGNED,

    -> gender ENUM('M','F') DEFAULT 'M'

    -> )ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

Query OK, 0 rows affected (0.00 sec)


// 验证

MariaDB [db1]> DESC student;

+--------+----------------------+------+-----+---------+----------------+

| Field  | Type                 | Null | Key | Default | Extra          |

+--------+----------------------+------+-----+---------+----------------+

| id     | smallint(5) unsigned | NO   | PRI | NULL    | auto_increment |

| name   | varchar(10)          | NO   |     | NULL    |                |

| age    | tinyint(3) unsigned  | YES  |     | NULL    |                |

| gender | enum('M','F')        | YES  |     | M       |                |

+--------+----------------------+------+-----+---------+----------------+

4 rows in set (0.00 sec)



'第一个注意点'    // 字段定义的重要性

// 插入数据  ( 注: 插入的值超过了 10 位, 有 12 位 '会被截断插入' )

MariaDB [db1]> insert student(name,age) values('wangxiaochun',20);

Query OK, 1 row affected, 1 warning (0.01 sec)    ( 报错有一个 warning )


// 查看 warning 信息

MariaDB [db1]> show warnings;

+---------+------+-------------------------------------------+

| Level   | Code | Message                                   |

+---------+------+-------------------------------------------+

| Warning | 1265 | Data truncated for column 'name' at row 1 |

+---------+------+-------------------------------------------+

1 row in set (0.00 sec)


// 查询表

MariaDB [db1]> select * from student;

+----+------------+------+--------+

| id | name       | age  | gender |

+----+------------+------+--------+

| 10 | wangxiaoch |   20 | M      |                # 多的字符没有被插入完全

+----+------------+------+--------+

1 row in set (0.00 sec)


// 插入数据

MariaDB [db1]> insert student(name,age,gender) values('xiaohong',18,'f');

Query OK, 1 row affected (0.001 sec)


// 查询表

MariaDB [db1]> select * from student;

+----+------------+------+--------+

| id | name       | age  | gender |

+----+------------+------+--------+

| 10 | wangxiaoch |   20 | M      |


| 11 | xiaohong   |   18 | F      |

+----+------------+------+--------+

2 rows in set (0.001 sec)


'第二个注意点'    // 数据库字符集的重要性

// 插入数据    ( 插入汉字 )

// 如果数据库字符集为 latin1, 会报错 ( 数值会乱码 )

MariaDB [db1]> insert student(name,age) values('王俊',18);

Query OK, 1 row affected, 1 warning (0.01 sec)


// 查询表

MariaDB [db1]> select * from student;

+----+------------+------+--------+

| id | name       | age  | gender |

+----+------------+------+--------+

| 10 | wangxiaoch |   20 | M      |


| 11 | xiaohong   |   18 | F      |

| 12 | ??         |   18 | M      |    // 如果数据库字符集为 latin1 ( 数值会乱码 )

+----+------------+------+--------+

3 rows in set (0.001 sec)


//

CREATE TABLE employee (id int UNSIGNED NOT NULL ,name VARCHAR(20) NOT NULL,age tinyint UNSIGNED,PRIMARY KEY(id,name));


// 查询 'student' 表的信息

// 这样的查询通常用于查看表的基本信息以及一些统计数据

// 以便于数据库管理员了解表的使用情况和性能特征

SHOW TABLE STATUS LIKE 'student';

SHOW TABLE STATUS LIKE 'student'\G

范例: auto_increment 属性

MariaDB [hellodb]> SHOW VARIABLES LIKE 'auto_inc%';

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| auto_increment_increment | 1     |

| auto_increment_offset    | 1     |

+--------------------------+-------+

2 rows in set (0.001 sec)


MariaDB [hellodb]> SET @@auto_increment_increment=10;

Query OK, 0 rows affected (0.001 sec)


MariaDB [hellodb]> SET @@auto_increment_offset=3;

Query OK, 0 rows affected (0.000 sec)


MariaDB [hellodb]> SHOW VARIABLES LIKE 'auto_inc%';

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| auto_increment_increment | 10    |

| auto_increment_offset    | 3     |

+--------------------------+-------+

2 rows in set (0.001 sec)


MariaDB [hellodb]> CREATE TABLE autoinc1 (col INT NOT NULL AUTO_INCREMENT PRIMARY KEY);

Query OK, 0 rows affected (0.004 sec)


MariaDB [hellodb]> INSERT INTO autoinc1 VALUES (NULL), (NULL), (NULL), (NULL);

Query OK, 4 rows affected (0.001 sec)

Records: 4 Duplicates: 0  Warnings: 0


MariaDB [hellodb]> SELECT col FROM autoinc1;

+-----+

| col |

+-----+

|   3 |

|  13 |

|  23 |

|  33 |

+-----+

4 rows in set (0.000 sec)

范例:

MariaDB [db1]> create table testdate (id int auto_increment primary key,date timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL);


MariaDB [db1]> insert testdate()values()()();

MariaDB [db1]> select * from testdate;

+----+---------------------+

| id | date                |

+----+---------------------+

|  1 | 2020-09-23 08:41:43 |

|  2 | 2020-09-23 08:41:43 |

|  3 | 2020-09-23 08:41:43 |

+----+---------------------+

3 row in set (0.000 sec)

(2)通过查询现存表创建;新表会被直接插入查询而来的数据

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options] [partition_options] select_statement

范例:

MariaDB [db1]> create table user select user,host,password from mysql.user;

Query OK, 4 rows affected (0.008 sec)

Records: 4 Duplicates: 0  Warnings: 0


MariaDB [db1]> show tables;

+---------------+

| Tables_in_db1 |

+---------------+

| student       |

| user          |

+---------------+

2 rows in set (0.000 sec)


MariaDB [db1]> desc user;

+----------+----------+------+-----+---------+-------+

| Field    | Type     | Null | Key | Default | Extra |

+----------+----------+------+-----+---------+-------+

| user     | char(80) | NO   |     |         |       |

| host     | char(60) | NO   |     |         |       |

| password | char(41) | NO   |     |         |       |

+----------+----------+------+-----+---------+-------+

(3)通过复制现存的表的表结构创建,但不复制数据

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_tbl_name | (LIKE old_tbl_name) }

范例:

// 查看表结构

MariaDB [db1]> desc student;

+--------+---------------------+------+-----+---------+----------------+

| Field  | Type                | Null | Key | Default | Extra          |

+--------+---------------------+------+-----+---------+----------------+

| id     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |

| name   | varchar(20)         | NO   |     | NULL    |                |

| age    | tinyint(3) unsigned | YES  |     | NULL    |                |

| gender | enum('M','F')       | YES  |     | M       |                |

+--------+---------------------+------+-----+---------+----------------+

4 rows in set (0.001 sec)


MariaDB [db1]> create table teacher like student;

Query OK, 0 rows affected (0.006 sec)


MariaDB [db1]> desc teacher;

+--------+---------------------+------+-----+---------+----------------+

| Field  | Type                | Null | Key | Default | Extra          |

+--------+---------------------+------+-----+---------+----------------+

| id     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |

| name   | varchar(20)         | NO   |     | NULL    |                |

| age    | tinyint(3) unsigned | YES  |     | NULL    |                |

| gender | enum('M','F')       | YES  |     | M       |                |

+--------+---------------------+------+-----+---------+----------------+

4 rows in set (0.001 sec)

范例: 创建外键表

mysql> create table school ( id int primary key auto_increment,name varchar(10));


mysql> create table teacher(id int primary key auto_increment,name varchar(10), school_id int,foreign key(school_id) references school(id));


mysql> desc school;

+-------+-------------+------+-----+---------+----------------+

| Field | Type        | Null | Key | Default | Extra          |

+-------+-------------+------+-----+---------+----------------+

| id    | int         | NO   | PRI | NULL    | auto_increment |

| name  | varchar(10) | YES  |     | NULL    |                |

+-------+-------------+------+-----+---------+----------------+

2 rows in set (0.00 sec)


mysql> desc teacher;

+-----------+-------------+------+-----+---------+----------------+

| Field     | Type        | Null | Key | Default | Extra          |

+-----------+-------------+------+-----+---------+----------------+

| id        | int         | NO   | PRI | NULL    | auto_increment |

| name      | varchar(10) | YES  |     | NULL    |                |

| school_id | int         | YES  | MUL | NULL    |                |

+-----------+-------------+------+-----+---------+----------------+

3 rows in set (0.00 sec)


mysql> show create table teacher;


mysql> insert school values(0,'magedu'),(0,'wangedu');

mysql> select * from school;

+----+---------+

| id | name    |

+----+---------+

|  1 | magedu  |

|  2 | wangedu |

+----+---------+

2 rows in set (0.00 sec)


mysql> insert teacher values(0,'xiaoming',1);

mysql> insert teacher values(0,'xiaohong',2);

Query OK, 1 row affected (0.00 sec)

mysql> select * from teacher;

+----+----------+-----------+

| id | name     | school_id |

+----+----------+-----------+

|  1 | xiaoming |         1 |

|  2 | xiaohong |         2 |

+----+----------+-----------+

2 rows in set (0.00 sec)


mysql> insert teacher values(0,'xiaobai',3);

3.5.2) 表查看

查看表:

SHOW TABLES [FROM db_name]

查看表创建命令:

SHOW CREATE TABLE tbl_name

查看表结构:

DESC [db_name.]tb_name

SHOW COLUMNS FROM [db_name.]tb_name

查看表状态:

SHOW TABLE STATUS LIKE 'tbl_name'

查看支持的 engine 类型

SHOW ENGINES;

范例:

MariaDB [db1]> show tables;

+---------------+

| Tables_in_db1 |

+---------------+

| student       |

+---------------+

1 row in set (0.000 sec)

范例:

// 查看表结构 方法 1

MariaDB [db1]> desc student;

+--------+---------------------+------+-----+---------+----------------+

| Field  | Type                | Null | Key | Default | Extra          |

+--------+---------------------+------+-----+---------+----------------+

| id     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |

| name   | varchar(20)         | NO   |     | NULL    |                |

| age    | tinyint(3) unsigned | YES  |     | NULL    |                |

| gender | enum('M','F')       | YES  |     | M       |                |

+--------+---------------------+------+-----+---------+----------------+

4 rows in set (0.001 sec)


// 查看表结构 方法 2

MariaDB [db1]> SHOW COLUMNS FROM student;

+--------+---------------------+------+-----+---------+----------------+

| Field  | Type                | Null | Key | Default | Extra          |

+--------+---------------------+------+-----+---------+----------------+

| id     | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |

| name   | varchar(20)         | NO   |     | NULL    |                |

| age    | tinyint(3) unsigned | YES  |     | NULL    |                |

| gender | enum('M','F')       | YES  |     | M       |                |

+--------+---------------------+------+-----+---------+----------------+

4 rows in set (0.001 sec)

范例:

MariaDB [db1]> show create table student;

范例:

// 查询 'student' 表的信息

MariaDB [db1]> SHOW TABLE STATUS LIKE 'student'\G

*************************** 1. row ***************************

           Name: student

          Engine: InnoDB

         Version: 10

      Row_format: Dynamic

           Rows:  0

  Avg_row_length: 0

     Data_length: 16384

 Max_data_length: 0

   Index_length:  0

       Data_free: 0

  Auto_increment: 10

     Create_time: 2020-02-17 11:35:29

     Update_time: NULL

     Check_time:  NULL

       Collation: latin1_swedish_ci

        Checksum: NULL

 Create_options:

         Comment:

Max_index_length: 0

       Temporary: N

1 row in set (0.001 sec)

查看库中所有表状态

SHOW TABLE STATUS FROM db_name

范例:

// 查询 'student' 表的信息

MariaDB [db1]> SHOW TABLE STATUS FROM db1\G

*************************** 1. row ***************************

           Name: employee

          Engine: InnoDB

         Version: 10

      Row_format: Dynamic

           Rows:  0

  Avg_row_length: 0

     Data_length: 16384

 Max_data_length: 0

   Index_length:  0

       Data_free: 0

  Auto_increment: NULL

     Create_time: 2020-02-17 11:43:21

     Update_time: NULL

     Check_time:  NULL

       Collation: latin1_swedish_ci

        Checksum: NULL

 Create_options:

         Comment:

Max_index_length: 0

       Temporary: N

       

*************************** 2. row ***************************

           Name: student

          Engine: InnoDB

         Version: 10

      Row_format: Dynamic

           Rows:  0

  Avg_row_length: 0

     Data_length: 16384

 Max_data_length: 0

   Index_length:  0

       Data_free: 0

  Auto_increment: 10

     Create_time: 2020-02-17 11:35:29

     Update_time: NULL

     Check_time:  NULL

       Collation: latin1_swedish_ci

        Checksum: NULL

 Create_options:

         Comment:

Max_index_length: 0

       Temporary: N

2 rows in set (0.001 sec)

3.5.3) 修改和删除表

ALTER TABLE 'tbl_name'


// 字段:

// 添加字段: add

ADD col1 data_type [FIRST|AFTER col_name]


// 删除字段: drop

// 修改字段:

alter(默认值), change(字段名), modify(字段属性)

查看修改表帮助

Help ALTER TABLE

删除表

DROP TABLE [IF EXISTS] 'tbl_name';

修改表范例

修改表名

ALTER TABLE students RENAME s1;


添加字段

// ALTER TABLE s1: 指定要修改的表名为 s1

// ADD: 表明要添加一个新的列

// phone: 这是新列的名称

// char(11): 指定新列的数据类型为字符型, 长度为 11.

// NOT NULL: 这是一个约束, 表示这个字段不能为 NULL, 即这个字段必须有值.

ALTER TABLE s1 ADD phone char(11) NOT NULL;


修改字段类型

// ALTER TABLE s1: 指定要修改的表名为 s1

// MODIFY: 表明要修改现有列的数据类型

// phone: 这是要修改的列的名称

// int: 这是要将列修改为的新数据类型

ALTER TABLE s1 MODIFY phone int;


修改字段名称和类型

// ALTER TABLE s1: 指定要修改的表名为 s1

// CHANGE COLUMN: 表明要修改现有的列

// phone: 这是要修改的列的当前名称

// mobile: 这是要将列修改为的新名称

// varchar(11): 这是要将列修改为的新数据类型, 即字符型, 长度为 11

ALTER TABLE s1 CHANGE COLUMN phone mobile varchar(11);


删除字段

ALTER TABLE students DROP age;


查看表结构

DESC students;


# 新建表无主键, 添加和删除主键

CREATE TABLE t1 SELECT * FROM students;


ALTER TABLE t1 add primary key (stuid);

ALTER TABLE t1 drop primary key;


# 添加外键

ALTER TABLE students add foreign key(TeacherID) references teachers(tid);


# 删除外键

SHOW CREATE TABLE students # 查看外键名

ALTER TABLE students drop foreign key <外键名>;

3.6)DML 语句

DML:INSERT,DELETE,UPDATE

3.6.1) INSERT 语句

功能: 一次插入一行或多行数据

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]

    [INTO] tbl_name [(col_name,...)]

    {VALUES | VALUE} ({expr | DEFAULT},...),(...),...

    [ ON DUPLICATE KEY UPDATE #如果重复更新之

     col_name=expr

        [, col_name=expr] ... ]

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]

    [INTO] tbl_name

    SET col_name={expr | DEFAULT}, ...

    [ ON DUPLICATE KEY UPDATE

     col_name=expr

        [, col_name=expr] ... ]

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]

    [INTO] tbl_name [(col_name,...)]

    SELECT ...

    [ ON DUPLICATE KEY UPDATE

     col_name=expr

        [, col_name=expr] ... ]

简化写法:

INSERT tbl_name [(col1,...)] VALUES (val1,...), (val21,...)

范例: 全值 插入

字段赋值需完整排序

// id 字段定义 0 没有关系 ( 该字段会自动递增 )

// gender 字段定义 default 没有关系 ( 该字段会默认定义为 M )

mysql> insert student values(0,'wang',18,default);

Query OK, 1 row affected (0.01 sec)

mysql> select * from student;

+----+------+------+--------+

| id | name | age  | gender |

+----+------+------+--------+

|  1 | wang |   18 | M      |

+----+------+------+--------+

1 row in set (0.00 sec)

范例: 部分列 插入

字段名与字段赋值一一对应

mysql> insert student(name,age) values('zhang',20);

Query OK, 1 row affected (0.01 sec)


// id 字段定义 default 没有关系 ( 该字段会自动递增 )

mysql> insert student(id,name,age) values(default,'li',19);

Query OK, 1 row affected (0.00 sec)


// id 字段定义 null 也没有关系 ( 该字段会自动递增 )

mysql> insert student(id,name,gender) values(null,'zhao','F');

Query OK, 1 row affected (0.00 sec)


mysql> select * from student;

+----+-------+------+--------+

| id | name  | age  | gender |

+----+-------+------+--------+

|  1 | wang  |   18 | M      |

|  2 | zhang |   20 | M      |

|  3 | li    |   19 | M      |

|  4 | zhao  | NULL | F      |

+----+-------+------+--------+

4 rows in set (0.00 sec)

3.6.2) UPDATE 语句

语法:

UPDATE [LOW_PRIORITY] [IGNORE] table_reference

SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ...

[WHERE where_condition]

[ORDER BY ...]

[LIMIT row_count]

注意: 一定要有限制条件,否则将修改指定字段的所有行

// 注意: 一定要有限制条件, 否则将修改指定字段的所有行

update student set gender='F';

//

'整数型'类型: 无需使用引号包含

'字符串'类型: 需要使用引号包含

update student set gender='F' where id=5;

update student set gender='F' where name='小红';

可利用 MySQL 选项避免此错误:

mysql -U | --safe-updates | --i-am-a-dummy

[root@centos8 ~] vim /etc/my.cnf

[mysql]

safe-updates

4.6.3) DELETE 语句

删除表中数据,但不会自动缩减数据文件的大小。

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name

[WHERE where_condition]

[ORDER BY ...]

[LIMIT row_count]

可先排序再指定删除的行数

注意: 一定要有限制条件,否则将清空表中的所有数据。

// 注意: 一定要有限制条件, 否则将清空表中的所有数据.

delete from student where id=5;

如果想清空表,保留表结构,也可以使用下面语句,此语句会自动缩减数据文件的大小。

TRUNCATE TABLE tbl_name;

缩减表大小

OPTIMIZE TABLE tb_name

范例: 删除数据可以使用逻辑删除,添加一个标识字段实现,删除数据即修改标识字段

mysql> alter table student add is_del bool default false;


mysql> desc student;

+--------+------------------+------+-----+---------+----------------+

| Field  | Type             | Null | Key | Default | Extra          |

+--------+------------------+------+-----+---------+----------------+

| id     | int unsigned     | NO   | PRI | NULL    | auto_increment |

| name   | varchar(20)      | NO   |     | NULL    |                |

| age    | tinyint unsigned | YES  |     | NULL    |                |

| gender | enum('M','F')    | YES  |     | M       |                |

| is_del | tinyint(1)       | YES  |     | 0       |                |

+--------+------------------+------+-----+---------+----------------+

5 rows in set (0.00 sec)

3.7)DQL 语句

3.7.1)单表查询

MySQL 基本总结 ( 学习ing

MySQL 常用命令:开放平台

MySQL 单表查询:开放平台

MySQL 多表查询:开放平台

MySQL 多表查询:开放平台

status        // 查询 MYSQL 版本

show databases;    // 查看所有数据库

use xxx;           // 使用数据库

show tables;       // 查看所有数据表


// 查询    ( 能查询部分字段的, 千万不要查询 *, 这样会增加查询时间 )

select * from 表名;        // 查询一个表中的所有数据

select 字段1,字段2,字段3 from 表名;    // 查询指定字段的数据


// 给字段取别名

select name from students;

select name as 姓名 from students;


// 给表取别名

SELECT

    [ALL | DISTINCT | DISTINCTROW ]

    [SQL_CACHE | SQL_NO_CACHE]

    select_expr [, select_expr ...]

        [FROM table_references

        [WHERE where_condition]

        [GROUP BY {col_name | expr | position}

            [ASC | DESC], ... [WITH ROLLUP]]

        [HAVING where_condition]

        [ORDER BY {col_name | expr | position}

            [ASC | DESC], ...]

        [LIMIT {[offset,] row_count | row_count OFFSET offset}]

        [FOR UPDATE | LOCK IN SHARE MODE]

说明:

字段显示可以使用别名:

col1 AS alias1,col2 AS alias2,...

WHERE 子句:指明过滤条件以实现 "选择" 的功能:

过滤条件:布尔型表达式

算术操作符:+, -, *, /, %

比较操作符:=,<=>(相等或都为空), <>, !=(非标准SQL), >, >=, <, <=

范例查询: BETWEEN min_num AND max_num

不连续的查询: IN (element1, element2, ...)

空查询: IS NULL, IS NOT NULL

DISTINCT 去除重复行,范例:SELECT DISTINCT gender FROM students;

模糊查询: LIKE 使用 % 表示任意长度的任意字符 _ 表示任意单个字符

RLIKE:正则表达式,索引失效,不建议使用

REGEXP:匹配字符串可用正则表达式书写模式,同上

逻辑操作符:NOT,AND,OR,XOR

GROUP BY:根据指定的条件把查询结果进行 "分组" 以用于做 "聚合" 运算

常见聚合函数: count(),sum(),max(),min(),avg()

注意:聚合函数不对 null 统计

HAVING:对分组聚合运算后的结果指定过滤条件

一旦分组 group by ,select 语句后只跟分组的字段,聚合函数

ORDER BY:根据指定的字段对查询结果进行排序

升序:ASC

降序:DESC

LIMIT [[offset,]row_count]:对查询的结果进行输出行数数量限制,跳过 offset,显示 row_count 行,offset 默为值为 0

对查询结果中的数据请求施加 "锁"

FOR UPDATE:写锁,独占或排它锁,只有一个读和写操作

LOCK IN SHARE MODE:读锁,共享锁,同时多个读操作

( '简单查询' )

// 查询 student 表所有字段的数据

select * from student;


// 查询 student 表所有字段的数据

// 然后过滤出那些性别字段值为 'F' 的记录

select * from student where gender='F';


// 查询 student 表 name,age,phone 字段的数据

// 然后过滤出那些性别字段值为 'F' 的记录

select name,age,phone from student where gender='F';

实验环境

MariaDB [(none)]> source /root/hellodb_innodb.sql


MariaDB [hellodb]> show tables;

+-------------------+

| Tables_in_hellodb |

+-------------------+

| classes           |

| coc               |

| courses           |

| scores            |

| students          |

| teachers          |

| toc               |

+-------------------+

7 rows in set (0.00 sec)


MariaDB [hellodb]> show create table students;

+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                    |

+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| students | CREATE TABLE `students` (

  `StuID` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `Name` varchar(50) NOT NULL,

  `Age` tinyint(3) unsigned NOT NULL,

  `Gender` enum('F','M') NOT NULL,

  `ClassID` tinyint(3) unsigned DEFAULT NULL,

  `TeacherID` int(10) unsigned DEFAULT NULL,

  PRIMARY KEY (`StuID`)

) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 |

+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)


MariaDB [hellodb]> select * from students;

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     1 | Shi Zhongyu   |  22 | M      |       2 |         3 |

|     2 | Shi Potian    |  22 | M      |       1 |         7 |

|     3 | Xie Yanke     |  53 | M      |       2 |        16 |

|     4 | Ding Dian     |  32 | M      |       4 |         4 |

|     5 | Yu Yutong     |  26 | M      |       3 |         1 |

|     6 | Shi Qing      |  46 | M      |       5 |      NULL |

|     7 | Xi Ren        |  19 | F      |       3 |      NULL |

|     8 | Lin Daiyu     |  17 | F      |       7 |      NULL |

|     9 | Ren Yingying  |  20 | F      |       6 |      NULL |

|    10 | Yue Lingshan  |  19 | F      |       3 |      NULL |

|    11 | Yuan Chengzhi |  23 | M      |       6 |      NULL |

|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL |

|    13 | Tian Boguang  |  33 | M      |       2 |      NULL |

|    14 | Lu Wushuang   |  17 | F      |       3 |      NULL |

|    15 | Duan Yu       |  19 | M      |       4 |      NULL |

|    16 | Xu Zhu        |  21 | M      |       1 |      NULL |

|    17 | Lin Chong     |  25 | M      |       4 |      NULL |

|    18 | Hua Rong      |  23 | M      |       7 |      NULL |

|    19 | Xue Baochai   |  18 | F      |       6 |      NULL |

|    20 | Diao Chan     |  19 | F      |       7 |      NULL |

|    21 | Huang Yueying |  22 | F      |       6 |      NULL |

|    22 | Xiao Qiao     |  20 | F      |       1 |      NULL |

|    23 | Ma Chao       |  23 | M      |       4 |      NULL |

|    24 | Xu Xian       |  27 | M      |    NULL |      NULL |

|    25 | Sun Dasheng   | 100 | M      |    NULL |      NULL |

+-------+---------------+-----+--------+---------+-----------+

25 rows in set (0.00 sec)

案例演示

// 查询年龄为 20 以下的行信息

select * from students where age <=20;


// 查询年龄为  20 - 30 之间的行信息

select * from students where age >=20 and age <=30;

select * from students where age between 20 and 30;


// 查询年龄为  18,20,22 的行信息

select * from students where age in (18,20,22);


// 只查看年龄列的行信息

select age from students;

select distinct age from students;    # 只查看不同值 ( 去重操作 )


// 查看 classid 为 NULL 值的行信息

select * from students where classid is null;

select * from students where classid is not null;    # 不为 NULL 值


// LIKE 模糊匹配

select * from students where name = 'Xi Ren';    # 精确查找

select * from students where name like 'Xi%';    # 模糊查找

select * from students where name like '%Xi%';   # 模糊查找

范例:

MariaDB [hellodb]> select password("hello world") ;

+-------------------------------------------+

| password("hello world")                   |

+-------------------------------------------+

| *67BECF85308ACF0261750DA1075681EE5C412F05 |

+-------------------------------------------+

1 row in set (0.000 sec)


MariaDB [hellodb]> select md5("hello world") ;

+----------------------------------+

| md5("hello world")               |

+----------------------------------+

| 5eb63bbbe01eeed093cb22bb8f5acdc3 |

+----------------------------------+

1 row in set (0.000 sec)

范例:字段别名

MariaDB [hellodb]> select stuid 学员ID,name as 姓名,gender 性别  from students;

+----------+---------------+--------+

| 学员ID   | 姓名          | 性别    |

+----------+---------------+--------+

|        1 | Shi Zhongyu   | M      |

|        2 | Shi Potian    | M      |

|        3 | Xie Yanke     | M      |

|        4 | Ding Dian     | M      |

|        5 | Yu Yutong     | M      |

|        6 | Shi Qing      | M      |

|        7 | Xi Ren        | F      |

|        8 | Lin Daiyu     | F      |

|        9 | Ren Yingying  | F      |

|       10 | Yue Lingshan  | F      |

|       11 | Yuan Chengzhi | M      |

|       12 | Wen Qingqing  | F      |

|       13 | Tian Boguang  | M      |

|       14 | Lu Wushuang   | F      |

|       15 | Duan Yu       | M      |

|       16 | Xu Zhu        | M      |

|       17 | Lin Chong     | M      |

|       18 | Hua Rong      | M      |

|       19 | Xue Baochai   | F      |

|       20 | Diao Chan     | F      |

|       21 | Huang Yueying | F      |

|       22 | Xiao Qiao     | F      |

|       23 | Ma Chao       | M      |

|       24 | Xu Xian       | M      |

|       25 | Sun Dasheng   | M      |

+----------+---------------+--------+

25 rows in set (0.000 sec)

范例:简单查询

DESC students;

INSERT INTO students VALUES(1,'tom','m'),(2,'alice','f');

INSERT INTO students(id,name) VALUES(3,'jack'),(4,'allen');

SELECT * FROM students WHERE id < 3;

SELECT * FROM students WHERE gender='m';

SELECT * FROM students WHERE gender IS NULL;

SELECT * FROM students WHERE gender IS NOT NULL;

SELECT * FROM students ORDER BY name DESC LIMIT 2;

SELECT * FROM students ORDER BY name DESC LIMIT 1,2;

SELECT * FROM students WHERE id >=2 and id <=4

SELECT * FROM students WHERE BETWEEN 2 AND 4

SELECT * FROM students WHERE name LIKE 't%'

SELECT * FROM students WHERE name RLIKE '.*[lo].*';

SELECT id stuid,name as stuname FROM students


select * from students where classid in (1,3,5);

select * from students where classid not in (1,3,5);

范例:判断是否为 NULL

MariaDB [hellodb]> select * from students where classid is null;

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name        | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|    24 | Xu Xian     |  27 | M      |    NULL |      NULL |

|    25 | Sun Dasheng | 100 | M      |    NULL |      NULL |

+-------+-------------+-----+--------+---------+-----------+

2 rows in set (0.002 sec)


MariaDB [hellodb]> select * from students where classid <=> null;

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name        | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|    24 | Xu Xian     |  27 | M      |    NULL |      NULL |

|    25 | Sun Dasheng | 100 | M      |    NULL |      NULL |

+-------+-------------+-----+--------+---------+-----------+

2 rows in set (0.000 sec)


MariaDB [hellodb]> select * from students where classid is not null;


# ifnull 函数判断指定的字段是否为空值,如果空值则使用指定默认值

mysql> select stuid,name,ifnull(classID,'无班级') from students where classid is null;

+-------+-------------+-----------------------------+

| stuid | name        | ifnull(classID,'无班级')    |

+-------+-------------+-----------------------------+

|    24 | Xu Xian     | 无班级                      |

|    25 | Sun Dasheng | 无班级                      |

+-------+-------------+-----------------------------+

2 rows in set (0.00 sec)

范例: 记录去重

MariaDB [hellodb]> select distinct gender from students ;

+--------+

| gender |

+--------+

| M      |

| F      |

+--------+

2 rows in set (0.001 sec)


// 将 age 和 gender 多个字段重复的记录去重

mysql> select distinct age,gender from students;

范例: SQL 注入攻击

// 创建表

create table user (id int primary key auto_increment ,name varchar(20) not null ,password varchar(30) not null );


// 查看表结构

desc user;


// 插入数据

insert user values(null,'admin','123456');

insert user values(null,'wangj','456789');


// 查询表内容

select * from user;


// 类比登录认证

select * from user where name='admin' and password='123456';    # 可以查询到结果代表账户密码正确.( 登录成功 )
// 实际上我们用如下方法也可以查询到内容 ( 类似 SQL 注入 )

// 为什么可以成功 ( 因为该 SQL 语句增加了一个 or 或者 1=1 )

// 1=1 成立, 就可以查询到数据 ( 黑客就可以使用该 SQL 注入方法基于任何身份登录系统 )

select * from user where name='admin' and password='' or '1=1';

select * from user where name='admin' and password='' or '1'='1';

// 包括如下方法也可以实现 ( -- 为注释 )

select * from user where name='admin'; -- ' and password='xxxxxx';

select * from user where name='admin'; # ' and password='xxxxx';

范例:分页查询

# 只取前 3 个

mysql> select * from students limit 0,3;

mysql> select * from students limit 3;

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name       | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|     1 | Shi Zhongyu |  22 | M     |       2 |         3 |

|     2 | Shi Potian |  22 | M     |       1 |         7 |

|     3 | Xie Yanke   |  53 | M     |       2 |        16 |

+-------+-------------+-----+--------+---------+-----------+

3 rows in set (0.00 sec)


mysql> select * from students limit 1,3;

+-------+------------+-----+--------+---------+-----------+

| StuID | Name       | Age | Gender | ClassID | TeacherID |

+-------+------------+-----+--------+---------+-----------+

|     2 | Shi Potian |  22 | M     |       1 |         7 |

|     3 | Xie Yanke |  53 | M     |       2 |        16 |

|     4 | Ding Dian |  32 | M     |       4 |         4 |

+-------+------------+-----+--------+---------+-----------+

3 rows in set (0.00 sec)


# 查询第 n 页的数据, 每页显示 m 条记录

mysql> select * from students limit (n-1) * m,m;

范例:聚合函数

mysql> select sum(age)/count(*) from students where gender ='M';

+-------------------+

| sum(age)/count(*) |

+-------------------+

|           33.0000 |

+-------------------+

1 row in set (0.00 sec)


mysql> select sum(age)/count(*) from students where gender ='F';

+-------------------+

| sum(age)/count(*) |

+-------------------+

|           19.0000 |

+-------------------+

1 row in set (0.00 sec)

范例: 分组统计

// 统计每个 classid 出现的数量

mysql> select classid 班级,count(*) 学员数量 from students group by classid;

+--------+--------------+

| 班级   | 学员数量     |

+--------+--------------+

|   NULL |            2 |

|      1 |            4 |

|      2 |            3 |

|      3 |            4 |

|      4 |            4 |

|      5 |            1 |

|      6 |            4 |

|      7 |            3 |

+--------+--------------+

8 rows in set (0.00 sec)



MariaDB [hellodb]> select classid 班级,gender 性别,count(*) 数量 from students group by classid,gender;

+--------+--------+--------+

| 班级   | 性别   | 数量   |

+--------+--------+--------+

|   NULL | M      |      2 |

|      1 | F      |      2 |

|      1 | M      |      2 |

|      2 | M      |      3 |

|      3 | F      |      3 |

|      3 | M      |      1 |

|      4 | M      |      4 |

|      5 | M      |      1 |

|      6 | F      |      3 |

|      6 | M      |      1 |

|      7 | F      |      2 |

|      7 | M      |      1 |

+--------+--------+--------+

12 rows in set (0.00 sec)


// 分组统计

select classid,avg(age) as 平均年龄 from students where classid > 3 group by classid having 平均年龄 >30 ;

select gender,avg(age) 平均年龄 from students group by gender having gender='M';


// 多个字段分组统计

select classid,gender,count(*) 数量 from students group by classid,gender;

select classid,gender,count(*) 数量 from students group by gender,classid;


// 平均值

MariaDB [hellodb]> select gender 性别,avg(age) 平均年龄 from students group by gender;

+--------+--------------+

| 性别   | 平均年龄     |

+--------+--------------+

| F      |      19.0000 |

| M      |      33.0000 |

+--------+--------------+

2 rows in set (0.00 sec)

**范例:**group_concat 函数实现分组信息的集合

mysql> select gender,group_concat(name) from students group by gender;

范例: 分组统计

// with rollup 分组后聚合函数统计后再做汇总

mysql> select gender,count(*) from students group by gender with rollup;

+--------+----------+

| gender | count(*) |

+--------+----------+

| F      |       10 |

| M      |       15 |

| NULL   |       25 |

+--------+----------+

3 rows in set (0.00 sec)


mysql> select gender,group_concat(name) from students group by gender with rollup;

范例: 分组统计

// 注意: 一旦使用分组 group by

// 我们在 select 后面的只跟 采用分组的列 或 聚合函数

// 不要将其它的列放在 select

 后面, 否则根据系统变量 SQL_MODE 的值不同而不同的结果


// 以下为 MySQL8.0.17 的执行结果

mysql> use hellodb

mysql> select classid,count(*) 数量 from students group by classid;

+---------+--------+

| classid | 数量   |

+---------+--------+

|       2 |      3 |

|       1 |      4 |

|       4 |      4 |

|       3 |      4 |

|       5 |      1 |

|       7 |      3 |

|       6 |      4 |

|    NULL |      2 |

+---------+--------+

8 rows in set (0.00 sec)


mysql> select classid,count(*),stuid 数量 from students group by classid;

mysql> select @@sql_mode;

// 以下是 Mariadb10.3.17 的执行结果

MariaDB [hellodb]> select classid, count(*), stuid  from students group by classid;

+---------+----------+-------+

| classid | count(*) | stuid |

+---------+----------+-------+

|    NULL |        2 |    24 |

|       1 |        4 |     2 |

|       2 |        3 |     1 |

|       3 |        4 |     5 |

|       4 |        4 |     4 |

|       5 |        1 |     6 |

|       6 |        4 |     9 |

|       7 |        3 |     8 |

+---------+----------+-------+

8 rows in set (0.001 sec)


MariaDB [hellodb]> select @@sql_mode;

范例: 排序

// 只取前 3 个

mysql> select * from students order by age desc limit 3;

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name       | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|    25 | Sun Dasheng | 100 | M     |   NULL  |     NULL  |

|     3 | Xie Yanke   |  53 | M     |       2 |        16 |

|     6 | Shi Qing    |  46 | M     |       5 |     NULL  |

+-------+-------------+-----+--------+---------+-----------+

3 rows in set (0.00 sec)


// 跳过前 3 个只显示后续的 2 个

mysql> select * from students order by age desc limit 3,2;

+-------+--------------+-----+--------+---------+-----------+

| StuID | Name         | Age | Gender | ClassID | TeacherID |

+-------+--------------+-----+--------+---------+-----------+

|    13 | Tian Boguang |  33 | M      |       2 |      NULL |

|     4 | Ding Dian    |  32 | M      |       4 |         4 |

+-------+--------------+-----+--------+---------+-----------+

2 rows in set (0.00 sec)


// 排序 ( 默认从小到大 )

select * from students order by age;


// 倒序

select * from students order by age desc;

范例: 排序

select classid,sum(age) from students where classid is not null group by

 classid   order by classid;


select classid,sum(age) from students group by classid having classid is not null order by classid;


select classid,sum(age) from students where classid is not null group by

 classid order by classid limit 2,3;


// 必须先过滤, 再排序

select * from students where classid is not null order by gender desc, age asc;


// 多列排序

select * from students order by gender desc, age asc;

**范例:**正序排序时将 NULL 记录排在最后

// 对 classid 正序排序, NULL 记录排在最后

select * from students order by -classid desc;

范例: 分组和排序

mysql> select classid,count(*) 数量  from students group by classid order by 数量;

+---------+--------+

| classid | 数量   |

+---------+--------+

|       5 |      1 |

|    NULL |      2 |

|       2 |      3 |

|       7 |      3 |

|       1 |      4 |

|       4 |      4 |

|       3 |      4 |

|       6 |      4 |

+---------+--------+

8 rows in set (0.00 sec)


# 分组后再排序

MariaDB [hellodb]> select gender,classid,avg(age) from students where classid is not null group by gender,classid order by gender,classid;

+--------+---------+----------+

| gender | classid | avg(age) |

+--------+---------+----------+

| F      |       1 |  19.0000 |

| F      |       3 |  18.3333 |

| F      |       6 |  20.0000 |

| F      |       7 |  18.0000 |

| F      |      77 |  18.0000 |

| F      |      93 |  18.0000 |

| M      |       1 |  21.5000 |

| M      |       2 |  35.2000 |

| M      |       3 |  23.0000 |

| M      |       4 |  23.6000 |

| M      |       5 |  46.0000 |

| M      |       6 |  23.0000 |

| M      |       7 |  23.0000 |

| M      |      94 |  18.0000 |

+--------+---------+----------+

14 rows in set (0.001 sec)


MariaDB [hellodb]> select * from students order by age limit 10;

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|    14 | Lu Wushuang   |  17 | F      |       3 |      NULL |

|     8 | Lin Daiyu     |  17 | F      |       7 |      NULL |

|    33 | Miejue Shitai |  18 | F      |      77 |      NULL |

|    32 | Zhang Sanfeng |  18 | M      |      94 |      NULL |

|    27 | liudehua      |  18 | F      |       1 |      NULL |

|    34 | Lin Chaoying  |  18 | F      |      93 |      NULL |

|    19 | Xue Baochai   |  18 | F      |       6 |      NULL |

|     7 | Xi Ren        |  19 | F      |       3 |      NULL |

|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL |

|    20 | Diao Chan     |  19 | F      |       7 |      NULL |

+-------+---------------+-----+--------+---------+-----------+

10 rows in set (0.001 sec)


MariaDB [hellodb]> select * from students order by age limit 3,10;

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|    34 | Lin Chaoying  |  18 | F      |      93 |      NULL |

|    19 | Xue Baochai   |  18 | F      |       6 |      NULL |

|    32 | Zhang Sanfeng |  18 | M      |      94 |      NULL |

|    27 | liudehua      |  18 | F      |       1 |      NULL |

|    20 | Diao Chan     |  19 | F      |       7 |      NULL |

|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL |

|    10 | Yue Lingshan  |  19 | F      |       3 |      NULL |

|    15 | Duan Yu       |  19 | M      |       4 |      NULL |

|     7 | Xi Ren        |  19 | F      |       3 |      NULL |

|    29 | wuyanzu       |  19 | M      |       4 |      NULL |

+-------+---------------+-----+--------+---------+-----------+

10 rows in set (0.000 sec)


MariaDB [hellodb]> select distinct age  from students order by age limit 3;

+-----+

| age |

+-----+

|  17 |

|  18 |

|  19 |

+-----+

3 rows in set (0.001 sec)


MariaDB [hellodb]> select distinct age  from students order by age limit 3,5;

+-----+

| age |

+-----+

|  20 |

|  21 |

|  22 |

|  23 |

|  25 |

+-----+

5 rows in set (0.001 sec)

范例: 分组和排序的次序

// 顺序: group by,having,order by

mysql> select classid,count(*) from students group by classid having classid is not null order by classid;

+---------+----------+

| classid | count(*) |

+---------+----------+

|       1 |        4 |

|       2 |        3 |

|       3 |        4 |

|       4 |        4 |

|       5 |        1 |

|       6 |        4 |

|       7 |        3 |

+---------+----------+

7 rows in set (0.00 sec)


// 以下顺序会出错, group by,order by,having

mysql> select classid,count(*) from students group by classid  order by classid having classid is not null;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'having classid is not null' at line 1


// 以下顺序会出错, order by,group by,having

mysql> select classid,count(*) from students order by classid group by classid having classid is not null;

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group by classid having classid is not null' at line 1

范例: 时间字段进行过滤查询,并且 timestamp 可以随其它字段的更新自动更新

MariaDB [testdb]>  create table testdate (id int auto_increment primary key,date timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);

MariaDB [testdb]>  insert testdate () values();

MariaDB [testdb]>  insert testdate values(),(),();


MariaDB [testdb]> select * from testdate;

+----+---------------------+

| id | date                |

+----+---------------------+

|  1 | 2020-06-03 15:21:03 |

|  2 | 2020-06-03 15:21:12 |

|  3 | 2020-06-03 15:21:14 |

|  4 | 2020-06-03 15:21:17 |

|  5 | 2020-06-03 18:27:39 |

|  6 | 2020-06-03 18:27:44 |

+----+---------------------+

6 rows in set (0.001 sec)


MariaDB [testdb]> select * from testdate where date between '2020-06-03 15:21:12' and '2020-06-03 18:27:40';

+----+---------------------+

| id | date                |

+----+---------------------+

|  2 | 2020-06-03 15:21:12 |

|  3 | 2020-06-03 15:21:14 |

|  4 | 2020-06-03 15:21:17 |

|  5 | 2020-06-03 18:27:39 |

+----+---------------------+

4 rows in set (0.000 sec)


MariaDB [testdb]> select * from testdate where date >= '2020-06-03 15:21:12' and date <= '2020-06-03 18:27:40';

+----+---------------------+

| id | date                |

+----+---------------------+

|  2 | 2020-06-03 15:21:12 |

|  3 | 2020-06-03 15:21:14 |

|  4 | 2020-06-03 15:21:17 |

|  5 | 2020-06-03 18:27:39 |

+----+---------------------+

4 rows in set (0.001 sec)


# 修改其它字段, 会自动更新 timestamp 字段

mysql> update testdate set id=10 where id=1;

mysql> select * from testdate3;

+----+---------------------+

| id | date                |

+----+---------------------+

|  2 | 2020-06-03 15:21:12 |

|  3 | 2020-06-03 15:21:14 |

|  4 | 2020-06-03 15:21:17 |

|  5 | 2020-06-03 18:27:39 |

|  6 | 2020-06-03 18:27:44 |

| 10 | 2020-06-03 18:34:51 |

+----+---------------------+

6 rows in set (0.001 sec)

3.7.2) 多表查询

多表查询即查询结果来自于多张表

**子查询:**在SQL语句嵌套着查询语句,性能较差,基于某语句的查询结果再次进行的查询

**联合查询:**UNION

**交叉连接:**笛卡尔乘积 CROSS JOIN

内连接:

等值连接:让表之间的字段以"等值"建立连接关系

不等值连接

自然连接:去掉重复列的等值连接 , 语法: FROM table1 NATURAL JOIN table2;

外连接:

**左外连接:**FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col

**右外连接:**FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col

完全外连接: FROM tb1 FULL OUTER JOIN tb2 ON tb1.col=tb2.col 注意:MySQL 不支持此 SQL 语法

**自连接:**本表和本表进行连接查询

3.7.2.1)子查询

子查询 subquery 即 SQL语句 调用另一个 SELECT 子句,可以是对同一张表,也可以是对不同表,主要有以下四种常见的用法。

// 举例

select * from students where age > (select avg(age) from students);

// 举例

update students set age= (select avg(age) from students) where stuid=25;

update teachers set age= (select avg(age) from students) where tid=4;

用于比较表达式中的子查询;子查询仅能返回单个值

SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM teachers);

update students set Age=(SELECT avg(Age) FROM teachers) where stuid=25;

用于 IN 中的子查询:子查询应该单独查询并返回一个或多个值重新构成列表

SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);

用于EXISTS 和 Not EXISTS

参考链接: MySQL :: MySQL 8.0 Reference Manual :: 13.2.15.6 Subqueries with EXISTS or NOT EXISTS

EXISTS(包括 NOT EXISTS)子句的返回值是一个 BOOL 值。

EXISTS 内部有一个子查询语句(SELECT ... FROM...),将其称为 EXIST 的内查询语句。

其内查询语句返回一个结果集。 EXISTS 子句根据其内查询语句的结果集空或者非空,返回一个布尔值。

将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果为非空值,则 EXISTS 子句返回 TRUE,外查询的这一行数据便可作为外查询的结果行返回,否则不能作为结果。

MariaDB [hellodb]> select * from students s where  EXISTS (select * from teachers t where s.teacherid=t.tid);

+-------+-------------+-----+--------+---------+-----------+

| StuID | Name        | Age | Gender | ClassID | TeacherID |

+-------+-------------+-----+--------+---------+-----------+

|     1 | Shi Zhongyu |  22 | M      |       2 |         3 |

|     4 | Ding Dian   |  32 | M      |       4 |         4 |

|     5 | Yu Yutong   |  26 | M      |       3 |         1 |

+-------+-------------+-----+--------+---------+-----------+


# 说明:

1) EXISTS (或 NOT EXISTS) 用在 where 之后, 且后面紧跟子查询语句 (带括号)

2) EXISTS (或 NOT EXISTS) 只关心子查询有没有结果, 并不关心子查询的结果具体是什么

3) 上述语句把 students 的记录逐条代入到 Exists 后面的子查询中, 如果子查询结果集不为空, 即说明

存在, 那么这条 students 的记录出现在最终结果集, 否则被排除.


MariaDB [hellodb]> select * from students s where NOT EXISTS (select * from teachers t where s.teacherid=t.tid);

+-------+---------------+-----+--------+---------+-----------+

| StuID | Name          | Age | Gender | ClassID | TeacherID |

+-------+---------------+-----+--------+---------+-----------+

|     2 | Shi Potian    |  22 | M      |       1 |         7 |

|     3 | Xie Yanke     |  53 | M      |       2 |        16 |

|     6 | Shi Qing      |  46 | M      |       5 |      NULL |

|     7 | Xi Ren        |  19 | F      |       3 |      NULL |

|     8 | Lin Daiyu     |  17 | F      |       7 |      NULL |

|     9 | Ren Yingying  |  20 | F      |       6 |      NULL |

|    10 | Yue Lingshan  |  19 | F      |       3 |      NULL |

|    11 | Yuan Chengzhi |  23 | M      |       6 |      NULL |

|    12 | Wen Qingqing  |  19 | F      |       1 |      NULL |

|    13 | Tian Boguang  |  33 | M      |       2 |      NULL |

|    14 | Lu Wushuang   |  17 | F      |       3 |      NULL |

|    15 | Duan Yu       |  19 | M      |       4 |      NULL |

|    16 | Xu Zhu        |  21 | M      |       1 |      NULL |

|    17 | Lin Chong     |  25 | M      |       4 |      NULL |

|    18 | Hua Rong      |  23 | M      |       7 |      NULL |

|    19 | Xue Baochai   |  18 | F      |       6 |      NULL |

|    20 | Diao Chan     |  19 | F      |       7 |      NULL |

|    21 | Huang Yueying |  22 | F      |       6 |      NULL |

|    22 | Xiao Qiao     |  20 | F      |       1 |      NULL |

|    23 | Ma Chao       |  23 | M      |       4 |      NULL |

|    24 | Xu Xian       |  27 | M      |    NULL |      NULL |

|    25 | Sun Dasheng   | 100 | M      |    NULL |      NULL |

+-------+---------------+-----+--------+---------+-----------+

22 rows in set (0.001 sec)

用于 FROM 子句中的子查询

使用格式:

SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause;

范例:

SELECT s.ClassID,s.aage FROM (SELECT ClassID,avg(Age) AS aage FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;

范例: 子查询

# 子查询: select 的执行结果, 被其它 SQL 调用

MariaDB [hellodb]> select stuid,name,age from students where age > (select avg(age) from students);

+-------+--------------+-----+

| stuid | name         | age |

+-------+--------------+-----+

|     3 | Xie Yanke    |  53 |

|     4 | Ding Dian    |  32 |

|     6 | Shi Qing     |  46 |

|    13 | Tian Boguang |  33 |

|    25 | Sun Dasheng  | 100 |

+-------+--------------+-----+

5 rows in set (0.00 sec)

范例: 子查询用于更新表

MariaDB [hellodb]> update teachers set age=(select avg(age) from students) where tid=4;

Query OK, 1 row affected (0.00 sec)


MariaDB [hellodb]> select * from teachers;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | Miejue Shitai |  77 | F      |

|   4 | Lin Chaoying  |  27 | F      |

+-----+---------------+-----+--------+

4 rows in set (0.00 sec)

3.7.2.2)联合查询

联合查询 Union 实现的条件,多个表的字段数量相同,字段名和数据类型可以不同,但一般数据类型是相同的。

SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;

范例: 联合查询

// 多表纵向合并 union

MariaDB [hellodb]> select * from teachers union select * from students;

MariaDB [hellodb]> select tid as id,name,age,gender from teachers union select stuid,name,age,gender from students;

+----+---------------+-----+--------+

| id | name          | age | gender |

+----+---------------+-----+--------+

|  1 | Song Jiang    |  45 | M      |

|  2 | Zhang Sanfeng |  94 | M      |

|  3 | Miejue Shitai |  77 | F      |

|  4 | Lin Chaoying  |  26 | F      |

|  1 | Shi Zhongyu   |  22 | M      |

|  2 | Shi Potian    |  22 | M      |

|  3 | Xie Yanke     |  53 | M      |

|  4 | Ding Dian     |  32 | M      |

|  5 | Yu Yutong     |  26 | M      |

|  6 | Shi Qing      |  46 | M      |

|  7 | Xi Ren        |  19 | F      |

|  8 | Lin Daiyu     |  17 | F      |

|  9 | Ren Yingying  |  20 | F      |

| 10 | Yue Lingshan  |  19 | F      |

| 11 | Yuan Chengzhi |  23 | M      |

| 12 | Wen Qingqing  |  19 | F      |

| 13 | Tian Boguang  |  33 | M      |

| 14 | Lu Wushuang   |  17 | F      |

| 15 | Duan Yu       |  19 | M      |

| 16 | Xu Zhu        |  21 | M      |

| 17 | Lin Chong     |  25 | M      |

| 18 | Hua Rong      |  23 | M      |

| 19 | Xue Baochai   |  18 | F      |

| 20 | Diao Chan     |  19 | F      |

| 21 | Huang Yueying |  22 | F      |

| 22 | Xiao Qiao     |  20 | F      |

| 23 | Ma Chao       |  23 | M      |

| 24 | Xu Xian       |  27 | M      |

| 25 | Sun Dasheng   | 100 | M      |

| 26 | xietingfeng   |  23 | M      |

| 27 | liudehua      |  18 | F      |

| 28 | mahuateng     |  20 | M      |

| 29 | wuyanzu       |  19 | M      |

| 30 | wuxin         |  21 | M      |

| 31 | Song Jiang    |  45 | M      |

| 32 | Zhang Sanfeng |  18 | M      |

| 33 | Miejue Shitai |  18 | F      |

| 34 | Lin Chaoying  |  18 | F      |

| 35 | 巴西可        |  20 | M      |

| 36 | abc           |  20 | M      |

+----+---------------+-----+--------+

40 rows in set (0.001 sec)

MariaDB [hellodb]> select * from teachers union select * from teachers;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | Miejue Shitai |  77 | F      |

|   4 | Lin Chaoying  |  93 | F      |

+-----+---------------+-----+--------+

4 rows in set (0.00 sec)


MariaDB [hellodb]> select * from teachers union all  select * from teachers;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | Miejue Shitai |  77 | F      |

|   4 | Lin Chaoying  |  93 | F      |

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | Miejue Shitai |  77 | F      |

|   4 | Lin Chaoying  |  93 | F      |


MariaDB [hellodb]> select * from user union select * from user;

+------+----------+----------+

| id   | username | password |

+------+----------+----------+

|    1 | admin    | magedu   |

|    2 | mage     | magedu   |

|    3 | wang     | centos   |

+------+----------+----------+

3 rows in set (0.00 sec)


MariaDB [hellodb]> select distinct  * from user ;

+------+----------+----------+

| id   | username | password |

+------+----------+----------+

|    1 | admin    | magedu   |

|    2 | mage     | magedu   |

|    3 | wang     | centos   |

+------+----------+----------+

3 rows in set (0.00 sec)

范例: 去重记录

mysql> select * from emp;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | mage          |  20 | M      |

|   4 | li            |  22 | F      |

|   3 | mage          |  20 | M      |

+-----+---------------+-----+--------+

5 rows in set (0.00 sec)


mysql> select distinct * from emp;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | mage          |  20 | M      |

|   4 | li            |  22 | F      |

+-----+---------------+-----+--------+

4 rows in set (0.00 sec)


mysql> select * from emp  union  select * from emp;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | mage          |  20 | M      |

|   4 | li            |  22 | F      |

+-----+---------------+-----+--------+

4 rows in set (0.00 sec)


# union all 不去重

mysql> select * from emp  union all select * from emp;

+-----+---------------+-----+--------+

| TID | Name          | Age | Gender |

+-----+---------------+-----+--------+

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | mage          |  20 | M      |

|   4 | li            |  22 | F      |

|   3 | mage          |  20 | M      |

|   1 | Song Jiang    |  45 | M      |

|   2 | Zhang Sanfeng |  94 | M      |

|   3 | mage          |  20 | M      |

|   4 | li            |  22 | F      |

|   3 | mage          |  20 | M      |

+-----+---------------+-----+--------+

10 rows in set (0.00 sec)

3.7.2.3) 交叉连接

cross join 即多表的记录之间做笛卡尔乘积组合,并且多个表的列横向合并相加,"雨露均沾"

**比如:**第一个表 3 行 4 列,第二个表 5 行 6 列,cross join 后的结果为 3*5 = 15 行,4+6 = 10列

交叉连接生成的记录可能会非常多,建议慎用

**范例:**交叉连接

// 横向合并, 交叉连接 (横向笛卡尔)

MariaDB [hellodb]> select * from students cross join teachers;

MariaDB [hellodb]> select * from teachers , students;

MariaDB [hellodb]> select stuid,students.name student_name,students.age,tid,teachers.name teacher_name,teachers.age from teachers cross join students;

MariaDB [hellodb]> select stuid,s.name student_name,s.age student_age,tid,t.name teacher_name,t.age teacher_age from teachers t cross join students s ;

3.7.2.4)内连接

inner join 内连接取多个表的交集

范例: 内连接

// 内连接 inner join

MariaDB [hellodb]> select * from students inner join teachers on students.teacherid=teachers.tid;


// 表定义别名

// 如果表定义了别名, 原表名将无法使用

MariaDB [hellodb]> select stuid,s.name as student_name ,tid,t.name as teacher_name from students as s inner join teachers as t on s.teacherid=t.tid;

+-------+--------------+-----+---------------+

| stuid | student_name | tid | teacher_name  |

+-------+--------------+-----+---------------+

|     5 | Yu Yutong    |   1 | Song Jiang    |

|     1 | Shi Zhongyu  |   3 | Miejue Shitai |

|     4 | Ding Dian    |   4 | Lin Chaoying  |

+-------+--------------+-----+---------------+

3 rows in set (0.00 sec)


MariaDB [hellodb]> select stuid,s.name studentname,s.age studentage,tid,t.name as teachername,t.age teacherage from students as s inner join teachers t on s.teacherid=t.tid;

+-------+-------------+------------+-----+---------------+------------+

| stuid | studentname | studentage | tid | teachername   | teacherage |

+-------+-------------+------------+-----+---------------+------------+

|     5 | Yu Yutong   |         26 |   1 | Song Jiang    |         45 |

|    25 | Sun Dasheng |        100 |   1 | Song Jiang    |         45 |

|     1 | Shi Zhongyu |         22 |   3 | Miejue Shitai |         77 |

|     4 | Ding Dian   |         32 |   4 | Lin Chaoying  |         93 |

+-------+-------------+------------+-----+---------------+------------+

4 rows in set (0.00 sec)


MariaDB [hellodb]> select * from students , teachers where students.teacherid=teachers.tid;


MariaDB [hellodb]> select s.name 学生姓名,s.age 学生年龄,s.gender 学生性别,t.name 老师姓名,t.age 老师年龄,t.gender 老师性别 from students s inner join teachers t on s.gender <> t.gender;


MariaDB [hellodb]> select stuid,s.name,tid,t.name from students s,teachers t where s.teacherid=t.tid;

+-------+-------------+-----+---------------+

| stuid | name        | tid | name          |

+-------+-------------+-----+---------------+

|     5 | Yu Yutong   |   1 | Song Jiang    |

|     1 | Shi Zhongyu |   3 | Miejue Shitai |

|     4 | Ding Dian   |   4 | Lin Chaoying  |

+-------+-------------+-----+---------------+

3 rows in set (0.00 sec)


// 内连接后过滤数据

MariaDB [hellodb]> select * from students s inner join teachers t on s.teacherid=t.tid and s.age > 30 ;

MariaDB [hellodb]> select * from students s inner join teachers t on

 s.teacherid=t.tid where s.age > 30 ;

自然连接

当源表和目标表共享相同名称的列时,就可以在它们之间执行自然连接,而无需指定连接列。

在使用纯自然连接时,如没有相同的列时,会产生交叉连接(笛卡尔乘积)

语法: (SQL:1999)SELECT table1.column, table2.column FROM table1 NATURAL JOIN table2;

范例:

MariaDB [db1]> create table t1 ( id int,name char(20));

MariaDB [db1]> create table t2 ( id int,title char(20));

MariaDB [db1]> insert t1 values(1,'mage'),(2,'wang'),(3,'zhang');

MariaDB [db1]> insert t2 values(1,'ceo'),(2,'cto');

MariaDB [db1]> select * from t1;

+------+-------+

| id | name |

+------+-------+

| 1 | mage |

| 2 | wang |

| 3 | zhang |

+------+-------+

3 rows in set (0.00 sec)

MariaDB [db1]> select * from t2;

+------+-------+

| id | title |

+------+-------+

| 1 | ceo |

| 2 | cto |

+------+-------+

2 rows in set (0.00 sec)

MariaDB [db1]> select * from t1 NATURAL JOIN t2;

+------+------+-------+

| id | name | title |

+------+------+-------+

| 1 | mage | ceo |

| 2 | wang | cto |

+------+------+-------+

2 rows in set (0.00 sec)

MariaDB [db1]> select t1.name,t2.title from t1 NATURAL JOIN t2;

+------+-------+

| name | title |

+------+-------+

| mage | ceo |

| wang | cto |

+------+-------+

2 rows in set (0.00 sec)

3.7.2.4)左和右外连接

**左连接:**以左表为主根据条件查询右表数据,如果根据条件查询右表数据不存在使用 null 值填充

**右连接:**以右表为主根据条件查询左表数据,如果根据条件查询左表数据不存在使用 null 值填充

范例: 左,右外连接

// 左外连接 left outer join

MariaDB [hellodb]> select s.stuid,s.name,s.age,s.teacherid,t.tid,t.name,t.age from students as s left outer join teachers as t on s.teacherid=t.tid;

+-------+---------------+-----+-----------+------+---------------+------+

| stuid | name          | age | teacherid | tid  | name          | age |

+-------+---------------+-----+-----------+------+---------------+------+

|     1 | Shi Zhongyu   |  22 |         3 |    3 | Miejue Shitai |   77 |

|     2 | Shi Potian    |  22 |         7 | NULL | NULL          | NULL |

|     3 | Xie Yanke     |  53 |        16 | NULL | NULL          | NULL |

|     4 | Ding Dian     |  32 |         4 |    4 | Lin Chaoying  |   93 |

|     5 | Yu Yutong     |  26 |         1 |    1 | Song Jiang    |   45 |

|     6 | Shi Qing      |  46 |      NULL | NULL | NULL          | NULL |

|     7 | Xi Ren        |  19 |      NULL | NULL | NULL          | NULL |

|     8 | Lin Daiyu     |  17 |      NULL | NULL | NULL          | NULL |

|     9 | Ren Yingying  |  20 |      NULL | NULL | NULL          | NULL |

|    10 | Yue Lingshan  |  19 |      NULL | NULL | NULL          | NULL |

|    11 | Yuan Chengzhi |  23 |      NULL | NULL | NULL          | NULL |

|    12 | Wen Qingqing  |  19 |      NULL | NULL | NULL          | NULL |

|    13 | Tian Boguang  |  33 |      NULL | NULL | NULL          | NULL |

|    14 | Lu Wushuang   |  17 |      NULL | NULL | NULL          | NULL |

|    15 | Duan Yu       |  19 |      NULL | NULL | NULL          | NULL |

|    16 | Xu Zhu        |  21 |      NULL | NULL | NULL          | NULL |

|    17 | Lin Chong     |  25 |      NULL | NULL | NULL          | NULL |

|    18 | Hua Rong      |  23 |      NULL | NULL | NULL          | NULL |

|    19 | Xue Baochai   |  18 |      NULL | NULL | NULL          | NULL |

|    20 | Diao Chan     |  19 |      NULL | NULL | NULL          | NULL |

|    21 | Huang Yueying |  22 |      NULL | NULL | NULL          | NULL |

|    22 | Xiao Qiao     |  20 |      NULL | NULL | NULL          | NULL |

|    23 | Ma Chao       |  23 |      NULL | NULL | NULL          | NULL |

|    24 | Xu Xian       |  27 |      NULL | NULL | NULL          | NULL |

|    25 | Sun Dasheng   | 100 |      NULL | NULL | NULL          | NULL |

+-------+---------------+-----+-----------+------+---------------+------+

25 rows in set (0.00 sec)


// 左外连接扩展

MariaDB [hellodb]> select * from students s left outer join teachers t on s.teacherid=t.tid  where t.tid is null;


// 多个条件的左外连接

MariaDB [hellodb]> select * from students s left outer join teachers t on s.teacherid=t.tid and s.teacherid is null;


// 先左外连接, 再过滤

MariaDB [hellodb]> select * from students s left outer join teachers t on s.teacherid=t.tid where s.teacherid is null;


// 右外连接

MariaDB [hellodb]> select * from students s right outer join teachers t on s.teacherid=t.tid;


// 右外连接的扩展用法

MariaDB [hellodb]> select * from students s right outer join teachers t on s.teacherid=t.tid  where s.teacherid is null;

3.7.2.5)完全外连接

MySQL 不支持完全外连接 full outer join 语法

范例: 完全外连接

# MySQL不支持完全外连接 full outer join, 利用以下方式法代替

MariaDB [hellodb]> select * from students left join teachers on students.teacherid=teachers.tid

    -> union

    -> select * from students right join teachers on students.teacherid=teachers.tid;

    

MariaDB [hellodb]> select s.stuid,s.name,s.age,t.tid,t.name,t.age  from students as s left join teachers as t on s.teacherid=t.tid

     -> union

     -> select s.stuid,s.name,s.age,t.tid,t.name,t.age  from students as s right join teachers as t on s.teacherid=t.tid;

+-------+---------------+------+------+---------------+------+

| stuid | name          | age  | tid  | name          | age  |

+-------+---------------+------+------+---------------+------+

|     1 | Shi Zhongyu   |   22 |    3 | Miejue Shitai |   77 |

|     2 | Shi Potian    |   22 | NULL | NULL          | NULL |

|     3 | Xie Yanke     |   53 | NULL | NULL          | NULL |

|     4 | Ding Dian     |   32 |    4 | Lin Chaoying  |   93 |

|     5 | Yu Yutong     |   26 |    1 | Song Jiang    |   45 |

|     6 | Shi Qing      |   46 | NULL | NULL          | NULL |

|     7 | Xi Ren        |   19 | NULL | NULL          | NULL |

|     8 | Lin Daiyu     |   17 | NULL | NULL          | NULL |

|     9 | Ren Yingying  |   20 | NULL | NULL          | NULL |

|    10 | Yue Lingshan  |   19 | NULL | NULL          | NULL |

|    11 | Yuan Chengzhi |   23 | NULL | NULL          | NULL |

|    12 | Wen Qingqing  |   19 | NULL | NULL          | NULL |

|    13 | Tian Boguang  |   33 | NULL | NULL          | NULL |

|    14 | Lu Wushuang   |   17 | NULL | NULL          | NULL |

|    15 | Duan Yu       |   19 | NULL | NULL          | NULL |

|    16 | Xu Zhu        |   21 | NULL | NULL          | NULL |

|    17 | Lin Chong     |   25 | NULL | NULL          | NULL |

|    18 | Hua Rong      |   23 | NULL | NULL          | NULL |

|    19 | Xue Baochai   |   18 | NULL | NULL          | NULL |

|    20 | Diao Chan     |   19 | NULL | NULL          | NULL |

|    21 | Huang Yueying |   22 | NULL | NULL          | NULL |

|    22 | Xiao Qiao     |   20 | NULL | NULL          | NULL |

|    23 | Ma Chao       |   23 | NULL | NULL          | NULL |

|    24 | Xu Xian       |   27 | NULL | NULL          | NULL |

|    25 | Sun Dasheng   |  100 | NULL | NULL          | NULL |

|  NULL | NULL          | NULL |    2 | Zhang Sanfeng |   94 |

+-------+---------------+------+------+---------------+------+

26 rows in set (0.01 sec)


# 完全外连接的扩展示例

MariaDB [hellodb]> select * from students s left outer join teachers t on s.teacherid=t.tid where t.tid is null union select * from students s right outer join teachers t on s.teacherid=t.tid where s.teacherid is null;


MariaDB [hellodb]> select * from (select s.stuid,s.name s_name,s.teacherid,t.tid,t.name t_name from students s left outer join teachers t on s.teacherid=t.tid union select s.stuid,s.name,s.teacherid,t.tid,t.name from students s right outer join teachers t on s.teacherid=t.tid) as a where a.teacherid is null or a.tid is null;

+-------+---------------+-----------+------+---------------+

| stuid | s_name        | teacherid | tid  | t_name        |

+-------+---------------+-----------+------+---------------+

|     2 | Shi Potian    |         7 | NULL | NULL          |

|     3 | Xie Yanke     |        16 | NULL | NULL          |

|     6 | Shi Qing      |      NULL | NULL | NULL          |

|     7 | Xi Ren        |      NULL | NULL | NULL          |

|     8 | Lin Daiyu     |      NULL | NULL | NULL          |

|     9 | Ren Yingying  |      NULL | NULL | NULL          |

|    10 | Yue Lingshan  |      NULL | NULL | NULL          |

|    11 | Yuan Chengzhi |      NULL | NULL | NULL          |

|    12 | Wen Qingqing  |      NULL | NULL | NULL          |

|    13 | Tian Boguang  |      NULL | NULL | NULL          |

|    14 | Lu Wushuang   |      NULL | NULL | NULL          |

|    15 | Duan Yu       |      NULL | NULL | NULL          |

|    16 | Xu Zhu        |      NULL | NULL | NULL          |

|    17 | Lin Chong     |      NULL | NULL | NULL          |

|    18 | Hua Rong      |      NULL | NULL | NULL          |

|    19 | Xue Baochai   |      NULL | NULL | NULL          |

|    20 | Diao Chan     |      NULL | NULL | NULL          |

|    21 | Huang Yueying |      NULL | NULL | NULL          |

|    22 | Xiao Qiao     |      NULL | NULL | NULL          |

|    23 | Ma Chao       |      NULL | NULL | NULL          |

|    24 | Xu Xian       |      NULL | NULL | NULL          |

|  NULL | NULL          |      NULL |    2 | Zhang Sanfeng |

|  NULL | NULL          |      NULL |    5 | abc           |

+-------+---------------+-----------+------+---------------+

23 rows in set (0.00 sec)

3.7.2.6)自连接

自连接,即表自身连接自身

范例: 自连接

# 自连接

MariaDB [hellodb]> select * from emp;

+------+----------+----------+

| id   | name     | leaderid |

+------+----------+----------+

|    1 | mage     |     NULL |

|    2 | zhangsir |        1 |

|    3 | wang     |        2 |

|    4 | zhang    |        3 |

+------+----------+----------+

4 rows in set (0.00 sec)


MariaDB [hellodb]> select e.name,l.name from emp as e inner join emp as l on e.leaderid=l.id;

+----------+----------+

| name     | name     |

+----------+----------+

| zhangsir | mage     |

| wang     | zhangsir |

| zhang    | wang     |

+----------+----------+

3 rows in set (0.00 sec)


MariaDB [hellodb]> select   e.name,IFNULL(l.name,'无上级')   from emp as e left join emp as l on e.leaderid=l.id;

+----------+----------+

| name     | name     |

+----------+----------+

| zhangsir | mage     |

| wang     | zhangsir |

| zhang    | wang     |

| mage     | NULL     |

+----------+----------+

4 rows in set (0.00 sec)


MariaDB [hellodb]> select e.name emp,IFNULL(l.name,'无上级') leader from emp as e left join emp as l on e.leaderid=l.id;

+----------+----------+

| emp      | leader   |

+----------+----------+

| zhangsir | mage     |

| wang     | zhangsir |

| zhang    | wang     |

| mage     | NULL     |

+----------+----------+

4 rows in set (0.000 sec)

范例: 三表连接

// 三张表连接示例

MariaDB [hellodb]> select name,course,score from students st inner join scores sc on st.stuid=sc.stuid inner join courses co on sc.courseid=co.CourseID;

+-------------+----------------+-------+

| name        | course         | score |

+-------------+----------------+-------+

| Shi Zhongyu | Kuihua Baodian |    77 |

| Shi Zhongyu | Weituo Zhang   |    93 |

| Shi Potian  | Kuihua Baodian |    47 |

| Shi Potian  | Daiyu Zanghua  |    97 |

| Xie Yanke   | Kuihua Baodian |    88 |

| Xie Yanke   | Weituo Zhang   |    75 |

| Ding Dian   | Daiyu Zanghua  |    71 |

| Ding Dian   | Kuihua Baodian |    89 |

| Yu Yutong   | Hamo Gong      |    39 |

| Yu Yutong   | Dagou Bangfa   |    63 |

| Shi Qing    | Hamo Gong      |    96 |

| Xi Ren      | Hamo Gong      |    86 |

| Xi Ren      | Dagou Bangfa   |    83 |

| Lin Daiyu   | Taiji Quan     |    57 |

| Lin Daiyu   | Jinshe Jianfa  |    93 |

+-------------+----------------+-------+

15 rows in set (0.000 sec)


MariaDB [hellodb]> select st.name,co.Course,sc.score from courses co inner join scores sc  on co.courseid=sc.courseid inner join students st on

 sc.stuid=st.stuid;

+-------------+----------------+-------+

| name        | Course         | score |

+-------------+----------------+-------+

| Shi Zhongyu | Kuihua Baodian |    77 |

| Shi Zhongyu | Weituo Zhang   |    93 |

| Shi Potian  | Kuihua Baodian |    47 |

| Shi Potian  | Daiyu Zanghua  |    97 |

| Xie Yanke   | Kuihua Baodian |    88 |

| Xie Yanke   | Weituo Zhang   |    75 |

| Ding Dian   | Daiyu Zanghua  |    71 |

| Ding Dian   | Kuihua Baodian |    89 |

| Yu Yutong   | Hamo Gong      |    39 |

| Yu Yutong   | Dagou Bangfa   |    63 |

| Shi Qing    | Hamo Gong      |    96 |

| Xi Ren      | Hamo Gong      |    86 |

| Xi Ren      | Dagou Bangfa   |    83 |

| Lin Daiyu   | Taiji Quan     |    57 |

| Lin Daiyu   | Jinshe Jianfa  |    93 |

+-------------+----------------+-------+

15 rows in set (0.001 sec)

3.7.3)SELECT 语句处理的顺序

查询执行路径中的组件:查询缓存、解析器、预处理器、优化器、查询执行引擎、存储引擎

SELECT 语句的执行流程:

FROM Clause --> WHERE Clause --> GROUP BY --> HAVING Clause -->SELECT --> ORDER BY --> LIMIT

练习题:( 重要 )

导入 hellodb.sql 生成数据库

在 students 表中,查询年龄大于25岁,且为男性的同学的名字和年龄

SELECT name,age FROM students WHERE age > 25 AND gender = 'M';

以 ClassID 字段 为分组依据,显示各组的平均年龄

SELECT ClassID,AVG(age) AS avg_age

FROM students

GROUP BY ClassID;

显示第 2 题中平均年龄大于 30 的分组及平均年龄

要显示第 2 题中平均年龄大于 30 的分组及其平均年龄,您可以使用第 2 题的查询作为子查询,并在外部查询中筛选出平均年龄大于 30 的分组。

SELECT ClassID, avg_age

FROM (

SELECT ClassID, AVG(age) AS avg_age

FROM students

GROUP BY ClassID

) AS avg_per_group

WHERE avg_age > 30;

显示以 L 开头的名字的同学的信息

SELECT * FROM students

WHERE name LIKE 'L%';

显示 TeacherID 非空的同学的相关信息

SELECT * FROM students

WHERE TeacherID IS NOT NULL;

以年龄排序后,显示年龄最大的前 10 位同学的信息

SELECT * FROM students

ORDER BY age DESC

LIMIT 10;

查询年龄大于等于 20 岁,小于等于 25 岁的同学的信息

SELECT * FROM students WHERE age >= 20 AND age <= 25;

以 ClassID 分组,显示每班的同学的人数

SELECT ClassID, COUNT(*) AS student_count

FROM students

GROUP BY ClassID;

以 Gender 分组,显示其年龄之和

SELECT Gender, SUM(age) AS total_age

FROM students

GROUP BY Gender;

以 ClassID 分组,显示其平均年龄大于 25 的班级

SELECT ClassID, AVG(age) AS avg_age

FROM students

GROUP BY ClassID

HAVING AVG(age) > 25;

以 Gender 分组,显示各组中年龄大于 25 的学员的年龄之和

SELECT Gender, SUM(age) AS total_age

FROM students

GROUP BY Gender

HAVING SUM(CASE WHEN age > 25 THEN age ELSE 0 END) > 0;

显示前 5 位同学的姓名、课程及成绩

显示其成绩高于 80 的同学的名称及课程

取每位同学各门课的平均成绩,显示成绩前三名的同学的姓名和平均成绩

显示每门课程课程名称及学习了这门课的同学的个数

显示其年龄大于平均年龄的同学的名字

显示其学习的课程为第 1、2,4 或第 7 门课的同学的名字

显示其成员数最少为 3 个的班级的同学中年龄大于同班同学平均年龄的同学

统计各班级中年龄大于全校同学平均年龄的同学

扩展( 多表查询 )

Mysql 多表查询详解_mysql多表查询-CSDN博客

// 多表查询 ( "两张表查询" )

MariaDB [hellodb]> select st.name,sc.courseid,sc.score from students st inner join scores sc on st.stuid=sc.stuid;

+-------------+----------+-------+

| name        | courseid | score |

+-------------+----------+-------+

| Shi Zhongyu |        2 |    77 |

| Shi Zhongyu |        6 |    93 |

| Shi Potian  |        2 |    47 |

| Shi Potian  |        5 |    97 |

| Xie Yanke   |        2 |    88 |

| Xie Yanke   |        6 |    75 |

| Ding Dian   |        5 |    71 |

| Ding Dian   |        2 |    89 |

| Yu Yutong   |        1 |    39 |

| Yu Yutong   |        7 |    63 |

| Shi Qing    |        1 |    96 |

| Xi Ren      |        1 |    86 |

| Xi Ren      |        7 |    83 |

| Lin Daiyu   |        4 |    57 |

| Lin Daiyu   |        3 |    93 |

+-------------+----------+-------+

15 rows in set (0.01 sec)
// 多表查询 ( "三张表查询" )

MariaDB [hellodb]> select st.name,co.course,sc.score from students st inner join scores sc on st.stuid=sc.stuid inner join courses co on sc.courseid=co.courseid;

+-------------+----------------+-------+

| name        | course         | score |

+-------------+----------------+-------+

| Shi Zhongyu | Kuihua Baodian |    77 |

| Shi Zhongyu | Weituo Zhang   |    93 |

| Shi Potian  | Kuihua Baodian |    47 |

| Shi Potian  | Daiyu Zanghua  |    97 |

| Xie Yanke   | Kuihua Baodian |    88 |

| Xie Yanke   | Weituo Zhang   |    75 |

| Ding Dian   | Daiyu Zanghua  |    71 |

| Ding Dian   | Kuihua Baodian |    89 |

| Yu Yutong   | Hamo Gong      |    39 |

| Yu Yutong   | Dagou Bangfa   |    63 |

| Shi Qing    | Hamo Gong      |    96 |

| Xi Ren      | Hamo Gong      |    86 |

| Xi Ren      | Dagou Bangfa   |    83 |

| Lin Daiyu   | Taiji Quan     |    57 |

| Lin Daiyu   | Jinshe Jianfa  |    93 |

+-------------+----------------+-------+

15 rows in set (0.00 sec)
相关推荐
苹果醋322 分钟前
2020重新出发,MySql基础,MySql表数据操作
java·运维·spring boot·mysql·nginx
小蜗牛慢慢爬行23 分钟前
如何在 Spring Boot 微服务中设置和管理多个数据库
java·数据库·spring boot·后端·微服务·架构·hibernate
hanbarger27 分钟前
nosql,Redis,minio,elasticsearch
数据库·redis·nosql
微服务 spring cloud1 小时前
配置PostgreSQL用于集成测试的步骤
数据库·postgresql·集成测试
先睡1 小时前
MySQL的架构设计和设计模式
数据库·mysql·设计模式
弗罗里达老大爷1 小时前
Redis
数据库·redis·缓存
仰望大佬0072 小时前
Avalonia实例实战五:Carousel自动轮播图
数据库·microsoft·c#
学不透java不改名2 小时前
sqlalchemy连接dm8 get_columns BIGINT VARCHAR字段不显示
数据库
一只路过的猫咪2 小时前
thinkphp6使用MongoDB多个数据,聚合查询的坑
数据库·mongodb