MySQL学习笔记-子查询和连接

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

MySQL学习笔记-子查询和连接

 

使客户端进入gbk编码方式显示:

mysql> SET NAMES gbk;

 

1.子查询

子查询的定义:

子查询(Subquery)是指出现在其他SQL语句内的SELECT子句。

例如:

 

 SELECT * FROM t1 WHERE col1 = (SELECT col2 FROM t2);

 

其中SELECT * FROM t1 称为Outer Query / Outer Statement (外部查询)

SELECT col2 FROM t2 , 被称为SubQuery  (子查询)

 

子查询的条件:

子查询指嵌套在查询内部 ,且必须始终出现在圆括号内。

子查询可以包含多个关键字或条件,

                如:DISTINCT,GROUP BY,ORDER BY,LIMIT函数等。

子查询的外部查询可以是:SELECT , INSERT , UPDATE , SET 或 DO

 

子查询的返回值:

子查询可以返回标量、一行、一列或子查询

 

2.使用比较运算符的子查询

使用比较运算符的子查询:

=、>、<、>=、<=、<>、!=、 <=>

语法结构:

operand(操作数)、comparison_operator (比较运算符)、subquery(子查询)

用ANY  、SOME 或ALL修饰的比较运算符

operand comparison_operator ANY (subquery)

operand comparison_operator SOME (subquery)

operand comparison_operator ALL (subquery)

 

1.语法结构  操作数  比较运算符 any(子查询)

            操作数  比较运算符 some(子查询)

            操作数  比较运算符 all(子查询)

2.适合于子查询有多个结果

3.any 和some结果一致 all与any、some 相反

 

例,从tdb_goods表中 查询平均价格,小数点保留2位,:

mysql> SELECT ROUND(avg(goods_price),2) AS avg_price FROM tdb_goods;+-----------+| avg_price |+-----------+|   5391.30 |+-----------+

 

查询平均价格以上的商品:

mysql> SELECT * FROM tdb_goods WHERE goods_price > 5391.30;

 

mysql> SELECT * FROM tdb_goods WHERE goods_price > (SELECT ROUND(AVG(goods_price),2) FROM tdb_goods);

 

 

查询超极本的列表,按价格升序排列:

mysql> SELECT * FROM tdb_goods WHERE goods_cate = '超级本' ORDER BY goods_price ASC;

 

  • 查询比超极本的最低价格高的列表,按价格降序的方式排列:

mysql> SELECT * FROM tdb_goods WHERE goods_price > ANY(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超级本') ORDER BY goods_price DESC;

 

  • 查询比超极本的最高价格高的列表,按价格降序的方式排列:

mysql> SELECT * FROM tdb_goods WHERE goods_price > ALL(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超级本') ORDER BY goods_price DESC;

 

 

3.使用[NOT]IN/EXISTS引发的子查询

子查询形式:

1.使用IN的子查询

2.使用[NOT]IN的子查询

  语法结构:operand comparison_operator [NOT] IN (subquery)

  =ANY 运算符与IN 等效,!=ALL或<>ALL运算符与NOT IN等效

3.使用[NOT]EXISTS的子查询(用的相对较少)

  如果子查询返回任何行,EXISTS将返回TRUE,否则为FALSE

例,查找不是超极本的商品列表:

mysql> SELECT * FROM tdb_goods WHERE goods_cate NOT IN(SELECT goods_cate FROM tdb_goods WHERE goods_cate = '超级本');

 

 

 

4.使用INSERT...SELECT插入记录

例:在tdb_goods_cates表中插入tdb_goods表中的goods_cate分类;

mysql> INSERT tdb_goods_cates(cate_name) SELECT goods_cate FROM tdb_goods GROUP BY goods_cate;
mysql> SELECT * FROM tdb_goods_cates;+---------+---------------------+| cate_id | cate_name           |+---------+---------------------+|       1 | 台式机              ||       2 | 平板电脑            ||       3 | 服务器/工作站       ||       4 | 游戏本              ||       5 | 笔记本              ||       6 | 笔记本配件          ||       7 | 超级本              |+---------+---------------------+

 

5.多表更新

多表更新:

UPDATE table_references SET col_name1={expr1|DEFAULT}[,col_name2={expr2|DEFAULT}]...[WHERE where_condition]

 

其中,table_references即连接的语法结构

 

连接类型:

INNER JOIN,内连接

   在MySQL中,JOIN,CROSS JOIN和INNER JOIN是等价的

LEFT [OUTER] JOIN,左外连接

RIGHT [OUTER] JOIN,右外连接

 

连接—语法结构

table_reference
{[INNER | CROSS] JOIN |{LEFT|RIGHT} [OUTER] JOIN}
table_referenceON conditional_expr

 

例,将tdb_goods中的goods_cate更新为tdb_goods_cate表中的对应cate_id。 

mysql> UPDATE tdb_goods INNER JOIN tdb_goods_cates ON goods_cate = cate_name SET goods_cate = cate_id;

 

 

6.多表更新之一步到位

CREATE...SELECT

创建数据表同时将查询结果写入到数据表(合并了CREATE 和 INSERT...SELECT两个操作步骤)

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

 

例:创建品牌分类数据表tdb_goods_brand,并将tdb_goods表中的brand_name写入

mysql> CREATE TABLE tdb_goods_brand(    -> brand_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,    -> brand_name VARCHAR(40) NOT NULL
    -> )    -> SELECT brand_name FROM tdb_goods GROUP BY brand_name;

 

  • 例,将tdb_goods中的brand_name更新为tdb_goods_brand表中的对应brand_id。错误写法(程序分别不出哪个brand_name属于哪个表):

mysql> UPDATE tdb_goods INNER JOIN tdb_goods_brand ON brand_name = brand_name SET brand_name = brand_id;
ERROR 1052 (23000): Column 'brand_name' in field list is ambiguous

 

解决方法是给表起别名:

mysql> UPDATE tdb_goods AS a INNER JOIN tdb_goods_brand AS b ON a.brand_name = b.brand_name SET a.brand_name = b.brand_id;

 

  • 查询tdb_goods的数据表结构

mysql>  DESC tdb_goods;+-------------+------------------------+------+-----+---------+----------------+| Field       | Type                   | Null | Key | Default | Extra          |+-------------+------------------------+------+-----+---------+----------------+| goods_id    | smallint(5) unsigned   | NO   | PRI | NULL    | auto_increment || goods_name  | varchar(150)           | NO   |     | NULL    |                || goods_cate  | varchar(40)            | NO   |     | NULL    |                || brand_name  | varchar(40)            | NO   |     | NULL    |                || goods_price | decimal(15,3) unsigned | NO   |     | 0.000   |                || is_show     | tinyint(1)             | NO   |     | 1       |                || is_saleoff  | tinyint(1)             | NO   |     | 0       |                |+-------------+------------------------+------+-----+---------+----------------+

 

goods_cate和brand_name任然是varchar,现在我们修改字段名goods_cate为cate_id,brand_name修改为brand_id,  为了节省空间,我们修改数据类型为smallant

mysql> ALTER TABLE tdb_goods;    -> CHANGE goods_cate cate_id SMALLINT UNSIGNED NOT NULL,    -> CHANGE brand_name brand_id SMALLINT UNSIGNED NOT NULL;
mysql> DESC tdb_goods;                                                                                    
+-------------+------------------------+------+-----+---------+----------------+| Field       | Type                   | Null | Key | Default | Extra          |+-------------+------------------------+------+-----+---------+----------------+| goods_id    | smallint(5) unsigned   | NO   | PRI | NULL    | auto_increment || goods_name  | varchar(150)           | NO   |     | NULL    |                || cate_id     | smallint(5) unsigned   | NO   |     | NULL    |                || brand_id    | smallint(5) unsigned   | NO   |     | NULL    |                || goods_price | decimal(15,3) unsigned | NO   |     | 0.000   |                || is_show     | tinyint(1)             | NO   |     | 1       |                || is_saleoff  | tinyint(1)             | NO   |     | 0       |                |+-------------+------------------------+------+-----+---------+----------------+

 

7.连接的语法结构

连接在MySQL在SELECT语句、多表更新、多表删除语句中支持JOIN操作。

table_reference
{[INNER|CROSS] JOIN|{LEFT|RIGHT}[OUTER]JOIN}
table_referenceON conditional_expr

 

数据表参照

table_reference

tbl_name [[AS] alias] | table_subquery [AS] alias

数据表可以使用tbl_name AS alias_name

或tbl_name alias_name 赋予别名

table_subquery可以作为子查询使用FROM子句中,

这样的子查询必须赋予别名。

 

8.内连接INNER JOIN

INNER JOIN,内连接

在MySQL中,JOIN,CROSS JOIN 和 INNER JOIN 是等价的

LEFT [OUTER] JOIN,左外连接

RIGHT [OUTER] JOIN,右外连接

连接条件:

使用ON关键字来设定连接条件,也可以使用WHERE来代替

通常使用ON关键字来设定连接条件

使用WHERE关键字进行结果集记录的过滤

 

内连接和外连接的区别

内连接 ,显示左表及右表符合连接条件的记录,即交集

例如 插入几条记录

-- 分别在tdb_goods_cates和tdb_goods_brands表插入记录

INSERT tdb_goods_cates(cate_name) VALUES('路由器'),('交换机'),('网卡');INSERT tdb_goods_brands(brand_name) VALUES('海尔'),('清华同方'),('神舟');

 

-- 在tdb_goods数据表写入任意记

INSERT tdb_goods(goods_name,cate_id,brand_id,goods_price) VALUES(' LaserJet Pro P1606dn 黑白激光打印机','12','4','1849');

 

例,查看符合内连接的记录,表中只出现商品表和品牌表都有的记录,这就是内连接(这里商品表为左表,分类表为右表):

mysql> SELECT goods_id,goods_name,cate_name,goods_price FROM tdb_goods-> INNER JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id;

 

 

 

9.外连接OUTER JOIN

左外连接

  • 显示左表的全部记录及右表符合连接条件的记录

  • 例,查看符合左外连接的记录,表中出现商品表的全部和2表表都有的记录,这就是左外连接(这里商品表为左表,分类表为右表)

mysql> SELECT goods_id,cate_name,goods_price FROM tdb_goods 
LEFT JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id;

 

 

 

  • 右外连接

 

  • 显示右表的全部记录及左表符合连接条件的记录

  • 例,查看符合右外连接的记录,表中出现品牌表的全部和2表表都有的记录,这就是右外连接(这里商品表为左表,分类表为右表)

mysql> SELECT goods_id,goods_name,cate_name,goods_price FROM tdb_goods 
RIGHT JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id;

 

 

 

10.多表连接

/**  

  多表的连接跟两张表的连接一样

  表的连接实质就是外键的逆向约束

*/

例,查看符合内连接的记录,表中只出现商品表和品牌表都有的记录,这就是内连接的多表连接(这里商品表为左表,品牌表和分类表为右表):

mysql> SELECT goods_id,goods_name,cate_name,brand_name,goods_price FROM tdb_goods    -> INNER JOIN tdb_goods_cates ON tdb_goods.cate_id = tdb_goods_cates.cate_id    -> INNER JOIN tdb_goods_brand ON tdb_goods.brand_id = tdb_goods_brand.brand_id;

 

 

11.无限级分类表设计

自身连接

 

  • 例,查找所有分类及其父类:

mysql> SELECT s.type_id,s.type_name,p.type_name FROM tdb_goods_types AS s LEFT JOIN tdb_goods_types AS  p ON s.parent_id = p.type_id;+---------+-----------------+-----------------+| type_id | type_name       | type_name       |+---------+-----------------+-----------------+|       1 | 家用电器        | NULL            ||       2 | 电脑、办公      | NULL            ||       3 | 大家电          | 家用电器        ||       4 | 生活电器        | 家用电器        ||       5 | 平板电视        | 大家电          ||       6 | 空调            | 大家电          ||       7 | 电风扇          | 生活电器        ||       8 | 饮水机          | 生活电器        ||       9 | 电脑整机        | 电脑、办公      ||      10 | 电脑配件        | 电脑、办公      ||      11 | 笔记本          | 电脑整机        ||      12 | 超级本          | 电脑整机        ||      13 | 游戏本          | 电脑整机        ||      14 | CPU             | 电脑配件        ||      15 | 主机            | 电脑配件        |+---------+-----------------+-----------------+

 

  • 例,查找所有分类及其子类:

mysql> SELECT p.type_id,p.type_name,s.type_name FROM tdb_goods_types AS p LEFT JOIN tdb_goods_types AS s ON s.parent_id = p.type_id; 
+---------+-----------------+--------------+| type_id | type_name       | type_name    |+---------+-----------------+--------------+|       1 | 家用电器        | 大家电       ||       1 | 家用电器        | 生活电器     ||       2 | 电脑、办公      | 电脑整机     ||       2 | 电脑、办公      | 电脑配件     ||       3 | 大家电          | 平板电视     ||       3 | 大家电          | 空调         ||       4 | 生活电器        | 电风扇       ||       4 | 生活电器        | 饮水机       ||       5 | 平板电视        | NULL         ||       6 | 空调            | NULL         ||       7 | 电风扇          | NULL         ||       8 | 饮水机          | NULL         ||       9 | 电脑整机        | 笔记本       ||       9 | 电脑整机        | 超级本       ||       9 | 电脑整机        | 游戏本       ||      10 | 电脑配件        | CPU          ||      10 | 电脑配件        | 主机         ||      11 | 笔记本          | NULL         ||      12 | 超级本          | NULL         ||      13 | 游戏本          | NULL         ||      14 | CPU             | NULL         ||      15 | 主机            | NULL         |+---------+-----------------+--------------+

 

  • 例,查找所有分类及其子类的数目

mysql> SELECT p.type_id,p.type_name,COUNT(s.type_name) FROM tdb_goods_types AS p LEFT JOIN tdb_goods_types AS s ON s.parent_id = p.type_id GROUP BY p.type_name ORDER BY p.type_id;+---------+-----------------+--------------------+| type_id | type_name       | COUNT(s.type_name) |+---------+-----------------+--------------------+|       1 | 家用电器        |                  2 ||       2 | 电脑、办公      |                  2 ||       3 | 大家电          |                  2 ||       4 | 生活电器        |                  2 ||       5 | 平板电视        |                  0 ||       6 | 空调            |                  0 ||       7 | 电风扇          |                  0 ||       8 | 饮水机          |                  0 ||       9 | 电脑整机        |                  3 ||      10 | 电脑配件        |                  2 ||      11 | 笔记本          |                  0 ||      12 | 超级本          |                  0 ||      13 | 游戏本          |                  0 ||      14 | CPU             |                  0 ||      15 | 主机            |                  0 |+---------+-----------------+--------------------+

 

  • 为tdb_goods_types添加child_count字段

mysql> UPDATE tdb_goods_types AS t1 INNER JOIN
    -> (SELECT p.type_id,p.type_name,count(s.type_name) AS child_count FROM tdb_goods_types AS p    -> LEFT JOIN tdb_goods_types AS s ON s.parent_id = p.type_id    -> GROUP BY p.type_name    -> ORDER BY p.type_id)AS t2    -> ON t1.type_id = t2.type_id    ->  SET t1.child_count = t2.child_count;
    
mysql> SELECT * FROM tdb_goods_types;+---------+-----------------+-----------+-------------+| type_id | type_name       | parent_id | child_count |+---------+-----------------+-----------+-------------+|       1 | 家用电器        |         0 |           2 ||       2 | 电脑、办公      |         0 |           2 ||       3 | 大家电          |         1 |           2 ||       4 | 生活电器        |         1 |           2 ||       5 | 平板电视        |         3 |           0 ||       6 | 空调            |         3 |           0 ||       7 | 电风扇          |         4 |           0 ||       8 | 饮水机          |         4 |           0 ||       9 | 电脑整机        |         2 |           3 ||      10 | 电脑配件        |         2 |           2 ||      11 | 笔记本          |         9 |           0 ||      12 | 超级本          |         9 |           0 ||      13 | 游戏本          |         9 |           0 ||      14 | CPU             |        10 |           0 ||      15 | 主机            |        10 |           0 |+---------+-----------------+-----------+-------------+

 

11.多表删除

DELETE tbl_name[.*][,tbl_name[.*]]...FROM table_references[WHERE where_condition]

 

例,查找重复记录:

mysql> SELECT goods_id,goods_name FROM tdb_goods GROUP BY goods_name having count(goods_name) >= 2;                
+----------+-----------------------------+| goods_id | goods_name                  |+----------+-----------------------------+|       18 |  HMZ-T3W 头戴显示设备       ||       19 | 商务双肩背包                |+----------+-----------------------------+

 

删除重复记录

mysql> DELETE t1 FROM tdb_goods AS t1    -> LEFT JOIN (SELECT goods_id,goods_name FROM tdb_goods GROUP BY goods_name having count(goods_name) >= 2) AS t2    -> ON t1.goods_name = t2.goods_name    -> WHERE t1.goods_id > t2.goods_id;

 

12.复制记录

复制编号为19,20的两条记录

mysql>  SELECT goods_id,goods_name,cate_id,brand_id FROM tdb_goods WHERE goods_id IN (19,20);+----------+------------------------------------+---------+----------+| goods_id | goods_name                         | cate_id | brand_id |+----------+------------------------------------+---------+----------+|       19 | 商务双肩背包                       |       6 |        7 ||       20 | X3250 M4机架式服务器 2583i14       |       3 |        1 |+----------+------------------------------------+---------+----------+

 

mysql> INSERT tdb_goods(goods_name,cate_id,brand_id) SELECT goods_name,cate_id,brand_id FROM tdb_goods WHERE goods_id IN(19,20);

 








      本文转自谢育政 51CTO博客,原文链接:http://blog.51cto.com/kurolz/1929134,如需转载请自行联系原作者


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
22天前
|
分布式计算 关系型数据库 数据处理
Dataphin常见问题之没有建表的权限如何解决
Dataphin是阿里云提供的一站式数据处理服务,旨在帮助企业构建一体化的智能数据处理平台。Dataphin整合了数据建模、数据处理、数据开发、数据服务等多个功能,支持企业更高效地进行数据治理和分析。
|
24天前
|
SQL 关系型数据库 MySQL
阿里云MySQL数据库价格、购买、创建账号密码和连接数据库教程
阿里云数据库使用指南:购买MySQL、SQL Server等RDS实例,选择配置和地区,完成支付。创建数据库和账号,设置权限。通过DMS登录数据库,使用账号密码访问。同地域VPC内的ECS需将IP加入白名单以实现内网连接。参考链接提供详细步骤。
364 3
|
1天前
|
SQL 关系型数据库 MySQL
DQL语言之连接查询(mysql)
DQL语言之连接查询(mysql)
|
4天前
|
关系型数据库 MySQL 数据安全/隐私保护
MySQL 安装及连接
MySQL 安装及连接
22 0
|
13天前
|
存储 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT *、分页查询的优化、合理使用连接、子查询的优化)(上)
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT *、分页查询的优化、合理使用连接、子查询的优化)(上)
|
15天前
|
关系型数据库 MySQL 数据安全/隐私保护
MySQL连接ERROR 2059 (HY000): Authentication plugin ‘caching_sha2_password‘ cannot be loaded
MySQL连接ERROR 2059 (HY000): Authentication plugin ‘caching_sha2_password‘ cannot be loaded
23 0
|
27天前
|
关系型数据库 MySQL 网络安全
连接rds获取连接参数
连接阿里云RDS或类似服务需参数:数据库实例Endpoint(服务地址)、端口号(默认3306/5432)、数据库名、用户名、密码。可能需SSL证书、VPC/安全组规则。使用命令行(如`mysql`)或第三方工具(如MySQL Workbench)连接,参数相同。在阿里云控制台可获取具体连接信息。
28 7
|
27天前
|
安全 关系型数据库 应用服务中间件
连接rds设置网络权限
连接阿里云RDS需关注:1) 设置白名单,允许特定IP访问;2) 选择合适网络类型,如VPC或经典网络;3) 确保VPC内路由与安全组规则正确;4) 同VPC内可使用内网地址连接;5) 可启用SSL/TLS加密增强安全性。记得遵循最小权限原则,确保数据库安全。不同服务商操作可能有差异,但基本流程相似。
21 9
|
27天前
|
弹性计算 关系型数据库 MySQL
连接rds确认环境准备
连接阿里云RDS数据库需准备和检查:1) 创建并配置RDS实例,设置安全组规则;2) 确保ECS与RDS在同一VPC或可通信,添加ECS IP到白名单;3) 在ECS上安装数据库客户端;4) 配置连接参数;5) 若启用SSL,配置客户端证书;6) 测试连接;7) 更新应用配置。参照阿里云官方文档进行操作。
20 9
|
8天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)

推荐镜像

更多