MySQL子查询Subquery语法介绍
admin
2023-05-16 17:42:14
0

下面讲讲关于MySQL子查询Subquery,文字的奥妙在于贴近主题相关。所以,闲话就不谈了,我们直接看下文吧,相信看完MySQL子查询Subquery这篇文章你一定会有所受益。

子查询, 是指在SQL语句中内嵌了一个SELECT查询, SELECT称为内层查询, 包含SELECTSQL称为外层查询. 其按照内层查询是否依赖于外层查询, 可以分为独立子查询和相关子查询.

为了演示方便, 有测试表tb1 tb2, 数据如下:

mysql> SELECT * FROM tb1;

+------+

| col1 |

+------+

|   3 |

|   9 |

+------+

2 rows in set (0.00 sec)

 

mysql> SELECT * FROM tb2;

+------+

| col1 |

+------+

|   2 |

|   3 |

|   8 |

+------+

3 rows in set (0.00 sec)

 

独立子查询, 是指内层和外层查询没有关联,不用进行联合查询. 和其相关的有三组关键字: ANY/ IN/ SOME, ALLEXISTS.

 

ANY/ IN/ SOME的语法是:

operand comparison_operator ANY (subquery)

operand IN (subquery)

operand comparison_operator SOME (subquery)

 

a. ANY关键字的含义是, 对于在子查询返回的列中的任一值, 如果表达式结果为TRUE的话, 则返回TRUE.

 

对于如下SQL, tb1包含(3, 9), tb2包含(2, 3, 8), 表达式结果为TRUE.

mysql> SELECT col1 FROM tb1 WHERE col1> ANY (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|   3 |

|   9 |

+------+

2 rows in set (0.00 sec)

 

b. 在子查询中, = ANY的别名是IN, 下面两个SQL返回是相同的.

mysql> SELECT col1 FROM tb1WHERE col1 = ANY (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|   3 |

+------+

1 row in set (0.00 sec)

 

mysql> SELECT col1 FROM tb1WHERE col1 IN (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|   3 |

+------+

1 row in set (0.00 sec)

 

c. ANY的别名是SOME, 下面两个SQL返回是相同的.

mysql> SELECT col1 FROM tb1WHERE col1 <> ANY (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|   3 |

|   9 |

+------+

2 rows in set (0.00 sec)

 

mysql> SELECT col1 FROM tb1WHERE col1 <> SOME (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|   3 |

|   9 |

+------+

2 rows in set (0.00 sec)

 

ALL的语法是:

operand comparison_operator ALL (subquery)

 

a. ALL关键字的含义是, 对于在子查询返回的列中的所有值, 如果表达式结果为TRUE的话, 则返回TRUE.

mysql> SELECT col1 FROM tb1WHERE col1 > ALL (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|   9 |

+------+

1 row in set (0.00 sec)

 

b. <> ALL的别名是NOT IN, 下面两个SQL返回是相同的.

mysql> SELECT col1 FROM tb1 WHERE col1 <> ALL (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|    9 |

+------+

1 row in set (0.00 sec)

 

mysql> SELECT col1 FROM tb1WHERE col1 NOT IN (SELECT col1 FROM tb2);

+------+

| col1 |

+------+

|    9 |

+------+

1 row in set (0.00 sec)

 

最后一组关键字是EXISTS.

 

a. EXISTS的含义是, 若子查询返回非空集, EXISTSTRUE, NOT EXISTSFALSE. 下面的SQL只是为了便于理解EXISTS,一般不这样用.

mysql>SELECT col1 FROM tb1 WHERE EXISTS (SELECT * FROMtb2);

+------+

| col1 |

+------+

|   3 |

|   9 |

+------+

  1. rows in set (0.00 sec)

 

b. 如下EXISTS子查询比较接近实际情况, 获取表tb1tb2中相同的记录. 可以看到其内层关联了外层表,这也就是下面说的相关子查询.

mysql> SELECTcol1 FROM tb1 WHERE EXISTS (SELECT * FROM tb2 WHERE tb2.col1 = tb1.col1);

+------+

| col1 |

+------+

|   3 |

+------+

1 row in set (0.00 sec)

 

 

相关子查询, 是指内层查询需要和外层查询的表相关联, 进行联合查询. 在上面已经看到了相关子查询的例子, 仔细体会下其和独立子查询语法上的差异.

 

 

另外, 如上面的SELECT col1 FROM tb1 WHERE EXISTS (SELECT * FROM tb2WHERE tb2.col1 = tb1.col1), 是和再上面的SELECT col1 FROM tb1 WHERE col1 IN (SELECT col1 FROM tb2)等价的,即可将IN的独立子查询和EXISTS的相关子查询相互改写, 那么两者有什么不同呢

 

在表tb2中加入一条记录(NULL), 其数据如下, tb1的不变:

mysql> SELECT * FROM tb2;

+------+

| col1 |

+------+

|   2 |

|   3 |

|   8 |

| NULL |

+------+

4 rows in set (0.00 sec)

 

找出在表tb1, 不在tb2中的记录, 目测结果应为9, 但返回却为空.

mysql> SELECT * FROM tb1 WHERE col1 NOTIN (SELECT col1 FROM tb2);

Empty set (0.00 sec)

 

为什么呢, 测试如下, 原来在有NULL值的情况下, NOT IN只返回NOT TRUENULL, FALSE. 就是在NULL的情况下, NOT IN永远不会返回结果.

mysql> SELECT 'a' NOT IN ('a', 'b',NULL);

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

| 'a' NOT IN ('a', 'b', NULL) |

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

|                    0 |

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

1 row in set (0.00 sec)

 

mysql> SELECT 'c' NOT IN ('a', 'b',NULL);

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

| 'c' NOT IN ('a', 'b', NULL) |

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

|                 NULL |

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

1 row in set (0.00 sec)

 

若想NOT IN返回结果, 要先过滤掉NULL, 这里也说明了不建议把数据存为NULL的原因.

mysql> SELECT * FROM tb1 WHERE col1 NOTIN (SELECT col1 FROM tb2 WHERE col1 IS NOT NULL);

+------+

| col1 |

+------+

|   9 |

+------+

1 row in set (0.00 sec)

 

使用EXISTS来写的话, 由于其是相关子查询,不用特殊考虑NULL的情况.

mysql> SELECT * FROM tb1 WHERE NOTEXISTS (SELECT col1 FROM tb2 WHERE tb2.col1 = tb1.col1);

+------+

| col1 |

+------+

|    9 |

+------+

1 row in set (0.00 sec)

  

对于子查询的性能优化, 以及改写为JOIN, 稍后会进行整理, 感兴趣可关注订阅号”数据库最佳实践”(DBBestPractice).

对于以上MySQL子查询Subquery相关内容,大家还有什么不明白的地方吗?或者想要了解更多相关,可以继续关注我们的行业资讯板块。

 

相关内容

热门资讯

13岁女孩被闺蜜胁迫卖淫,父亲... 2022年6月,魏潇(化名)从得知时年13岁的女儿遭胁迫卖淫开始,便踏上了维权之路。4年来,胁迫其女...
苹果突然官宣!降到史上最低价! 近日 iPhone手机降价的消息刷屏了 网友纷纷发帖称 “零点确定降价了” “苹果坚挺了8个月终于降...
石化机械获得实用新型专利授权:... 证券之星消息,根据天眼查APP数据显示石化机械(000852)新获得一项实用新型专利授权,专利名为“...
小区2.82亩绿地“被交易”变... 近日,西安市世纪颐园小区业主向华商报大风新闻反映,小区西侧一块原本规划为公共绿地的土地,在多年前被开...
黄仁勋喝蜜雪冰城,品出了什么味... 每经评论员 朱成祥黄仁勋近期到访北京,被拍到在胡同喝豆汁、吃炸酱面、举着蜜雪冰城饮料。他表情轻松,与...
力箭系列率先实现民商火箭“百星... 来源:滚动播报 (来源:千龙网) 昨天(15日)12时33分,中科宇航力箭一号遥十三运载火箭在东风商...
B站独家直播中科院公众科学日:... 央广网北京5月16日消息(记者 殷雨婷)5月16日至17日,中国科学院第22届公众科学日在全国一百余...
飞沃科技获得实用新型专利授权:... 证券之星消息,根据天眼查APP数据显示飞沃科技(301232)新获得一项实用新型专利授权,专利名为“...
段永平的“本分”哲学,被OPP... 短短几十字的母亲节宣传文案,把OPPO推上了风口浪尖。 5月8日,手机品牌OPPO的官方微博、小红书...
百余家科创企业齐聚新疆 探索人... 乌鲁木齐5月15日电 (胡嘉琛)与机器人踢足球、遛机器狗……刚果(金)在华留学生基韦尼15日在乌鲁木...