MySQL多表记录操作(子查询、连接)

子查询:

概念:是指出现在其他 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

分类:

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

    符号:=、>、<、>=、<=、<>、!=、<=>

    语法结构:

    operand comparison_operator subquery

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

    说明:

    当查询记录返回有多个结果的时候,可以使用以上3个关键字来修饰,其中,ANY 和   

    SOME 是等价的,只需符合其中一个结果即可,而 ALL 则需要符合全部结果  

    原则:

    当 >、>= 结果时,ANY 取最小值,SOME 取最小值,ALL 取最大值

    当 <、<= 结果时,ANY 取最大值,SOME 取最大值,ALL 取最小值

    当 = 结果时,ANY 取任意值,SOME 取任意值

    当 <>、!= 结果时,ALL 取任意值

    语法结构:

    operand comparison_operator ANY (subquery)

    operand comparison_operator SOME (subquery)

    operand comparison_operator ALL (subquery)

⑶ 使用 [ NOT ] IN 的子查询

    语法结构:

    operand comparison_operator [NOT] IN (subquery) 

    = ANY 运算符与 IN 等效

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

⑷ 使用 [ NOT ] EXISTS 的子查询

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

案例:

创建一张简单的商品表:

其中,goods_name 为商品名称,goods_cate 为商品分类,brand_name 为品牌,

goods_price 为商品价格,is_show 为是否上架(1:上架,0:下架),

is_saleoff 为是否售罄(0:有货,1:售罄)

插入以下数据:

查询所有商品的平均价格:

对结果四舍五入并保留2位小数:

通过子查询来查询所有大于平均价格的商品:

查询所有女装:

由于记录较少,可以看出女装的最低价是229,查询下哪些商品的价格大于女装:

由图可以得出,使用 ANY (或者 SOME) 所得的结果中最低的价格大于或等于女装的最低价。

当使用 ALL 关键字时:

可以看出,所得结果的最低价大于或等于女装中最高的价格。

对于这张表来说,一些商品属于同个分类或者同个品牌,而且这些值都是中文字符,这就导致所占的字节数比数字还多,同时也会引发后续大量记录查询的效率问题。所以最好的办法是使用外键来实现,如果使用外键,至少得有2张数据表。

创建一张商品分类表:

我们需要把表 tb_goods 里的分类数据插入到表 tb_goods_cate 中,查看下总共有几种分类:

可以得出,商品里总共有3中分类,女装,男装和童装。

INSERT ... SELECT :

概念:

将查询的结果插入数据表

语法结构:

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

案例:

将商品中所有的分类记录插入到分类表中:

现在我们通过分类表去更新商品表,即把商品表的分类名称修改为对应的分类 id 。

当要同时操作多张表时,这时,我们需要对多张表进行连接。

CREATE .. SELECT:

概念:

创建数据表同时将查询结果写入到数据表中

语法结构:

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

案例:

新建一张商品品牌表,并把商品表中的品牌插入到表中:

创建成功,查询下品牌表的记录:

多表连接:

关键字:JOIN 

概念:MySQL 在 SELECT 语句、多表更新、多表删除语句中支持 JOIN 操作。

语法结构:

table_reference(起始表)

{ [ INNER | CROSS ] JOIN | { LEFT | RIGHT } [ OUTER ] JOIN }(连接类型)

table_reference(连接表)

ON conditional_expr(连接条件)

类型:

⑴ 内连接(INNER JOIN、JOIN、CROSS JOIN)

    表示左表和右表都符合连接条件的记录

⑵ 左外连接(LEFT [OUTER] JOIN)

    表示左表的全部记录和右表符合连接条件的记录,如果右表没有记录,则显示为 NULL 

⑶ 右外连接(RIGHT [OUTER] JOIN)

    与左外连接相反

数据表参照:

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

当两张表或多张表之间存在重复的字段名称时,尽量使用别名来进行区分。

比如:tbl_name AS alias_name 或 tbl_name alias_name 赋予别名。

table_subquery 可以作为子查询使用在 FROM 字句中,这样的子查询必须为其赋予别名。

连接条件:

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

通常使用 ON 关键字来设定连接条件,使用 WHERE 关键字进行结果集记录的过滤。

说明:

A LEFT JOIN B join_condition

数据表 B 的结果集依赖数据表 A

数据表 A 的结果集根据左连接条件依赖所有数据表(B 表除外)。

左外连接条件决定如何检索数据表 B (在没有指定 WHERE 条件的情况下)。

如果数据表 A 的某条记录符合 WHERE 条件,但是在数据表 B 不存在,符合连接条件的记录,将生成一个所有列为空的额外的 B 行。

如果使用内连接查询的记录在连接数据表中不存在,并且在 WHERE 子句中尝试以下操作:col_name 允许为 NULL 时,如果 col_name 被定义为 NOT NULL,MySQL 将在找到符合连接条件的记录后停止搜索更多的行。

多表更新:

语法结构:

UPDATE table_references SET col_name1 = { expr1 | DEFAULT }

[ ,col_name2 = { expr2 | DEFAULT }] ...

[ WHERE where_condition ]

其中, table_references(表的参照关系)的语法结构对应多表连接的语法结构。

案例:

将商品表的分类名称修改为对应分类表的 id:

再查询一下商品表的记录:

可以发现,所有的商品分类名称都修改为了分类 id 。

继续,参照刚才修改分类的方法把商品表的品牌名称修改为品牌表中的品牌 id:

可以看到系统提示错误,字段 brand_name 模糊不清,因为在两张表中存在重复的 brand_name 字段,系统并不知道该字段所隶属的是哪张表,所以这个时候需要给表取别名:

对表 tb_goods 取别名为 g,表 tb_goods_brand 取别名为 b,并且在连接条件和修改的值里面指定表的字段。再来查看一下表 tb_goods 的记录:

可以发现,品牌的值全部修改为了品牌表中的品牌 id 了。

查看下商品表的结构:

虽然品牌和分类已经修改为了对应的 id ,但是字段类型还是字符型,字段名称也不够清晰明了,所以尽量把字段名称和字段类型修改为对应的 id 和整型:

再来查看下商品表的结构:

可以发现,原来的 goods_cate 和 goods_brand 已经修改为了 cate_id 和 brand_id。

多表查询:

分别对商品表、分类表和品牌表添加记录:

商品表
分类表
品牌表

内连接:

可以发现,id = 19 的记录并没有返回,因为该记录的分类 id = 8 不存在于商品的分类表中,不符合连接条件,所以该结果没有返回。同样,在分类表和品牌表里新增的记录里,由于在商品表中并没有该分类的记录,所以也没有返回结果。

左外连接:

可以发现,左表(商品表)返回了全部记录,右表(分类表)返回符合条件的记录,如果没有符合条件的,则显示为 NULL

右外连接:

同理,右表(分类表)返回所有记录,左表(商品表)返回符合条件的记录,没有记录则显示 NULL

以上 3 中连接方式,常用的是内连接。

通过对商品表,分类表和品牌表 3 张表进行连接查询:

当我们类目有子类目,子类目又有子类目时,这样的结构可以通过一张表来实现:

其中,parent_id 指该类目的父级类目的 id ,如果 parent_id = 0 说明该类目为顶级类目。

自身连接:

概念:同一个数据表对其自身进行连接。

准备一张课程类目表(总共有 70 条,部分截图):

场景一,查找所有的子类所隶属的父类:

思路:在右侧想象一张和当前表一样的数据表(子表),进行多表连接,所以父表中的字段 parent_id 已经不需要了,因为子表中的 parent_id 指向的是父表中的 id 。

参照表以子表为主,查询一下:

其中,s 代表的是子表,p 代表的是父表。

场景二,查找父类下的所有子类:

参照表以父表为主。

场景三,查找父类下有多少个子类

先对场景二所查询的表的父级名称进行分组:

当出现以上情况时,通过以下操作解决:

mysql > 

set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

mysql > 

set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

设置完成后重新分组,返回结果如下:

对 id 进行升序排列。

查看父类底下有多少个子类:

多表删除:

语法结构:

DELETE tbl_name[ .* ] [ ,tbl_name[ .* ] ...

FROM table_references [ WHERE where_condition ]

查询表 tb_goods 里的数据:

查找商品表里重复的记录:

可以发现表里存在两条以上重复的记录。(单表模拟多表连接查询,将查询出来的结果模拟一张表)

通过子查询删除重复数据:

给表 tb_goods 取别名为 t1 ,将子查询中返回的结果取别名为 t2。

再查询下商品表的记录:

由图可以看出,重复的记录(迷彩针织裤)已经被删除,且留下 id 最小的那条记录。

内容较多,需多练习,反复斟酌。

以上为本人的一些学习笔记,如有出错欢迎指正,陆续更新!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 数据准备 回顾 记录操作:写操作:INSERT,UPDATE,DELETE读取操作:SELECT 这章主要学习:子...
    齐天大圣李圣杰阅读 1,047评论 0 4
  • 1、创建练习使用的数据表 goods_id —— 商品编号goods_name —— 商品名称goods_cate...
    黒猫阅读 982评论 0 4
  • 1、MySQL启动和关闭(安装及配置请参照百度经验,这里不再记录。MySQL默认端口号:3306;默认数据类型格式...
    强壮de西兰花阅读 631评论 0 1
  • 一、mysql查询的五种子句 where(条件查询)、having(筛选)、group by(分组)、order ...
    化城阅读 1,559评论 0 9
  • 佛说 修行 不需要过往的牵挂 我忘却尘缘 云游四方 追寻成佛的路 过往的云烟 汇着你的生生世世 化成十月的昙花 时...
    诸葛熊猫阅读 235评论 0 6