美文网首页
MySQL | 数据查询语言之子查询

MySQL | 数据查询语言之子查询

作者: 82a7fe2508f4 | 来源:发表于2022-04-25 10:53 被阅读0次

子查询

分治思想. 复杂的查询分解为若干个简单的查询

▲ 子查询的引入

#找出商店售价比 诺基亚E66 要贵的产品的信息

s1. get 诺基亚E66 price

SELECT shop_price FROM ecs_goods

WHERE goods_name = '诺基亚E66';

#2298.00

s2. ALL price > 2298.0

SELECT * FROM ecs_goods

WHERE shop_price > 2298.0;

SELECT * FROM ecs_goods

WHERE shop_price > (SELECT shop_price FROM ecs_goods

WHERE goods_name = '诺基亚E66');

1、子查询定义与分类

▲ 定义

子查询本质上就是一个select表达式(凡是能返回一个虚表的式子),可以嵌套在select语句的子句中,其返回的结果可以被select语句所用.

▲ 分类

根据其返回的行与列的个数不同分类:

○ 表子查询

其返回的结果是一个虚表.

rows >= 1 cols >= 1

○ 标量子查询

其返回的结果是一个值.

rows = 1 cols = 1

其他分类方式:

外层查询 内层查询

父查询 子查询

▲ 子查询的使用场合

2、select后的子查询

select子句后只能放置标量子查询,要求每次只能返回一个值.

语法:

select ... (select expression) ...

from tabs

where search_condition

order by sort_columns;

#列出商品表中各商品的类型名称

SELECT goods_id,

(SELECT cat_name FROM ecs_goods_type WHERE cat_id = g.goods_type) AS type_name,

goods_name

FROM ecs_goods g

ORDER BY 2;

#模拟Oracle的rownum(行编号)

SELECT (SELECT COUNT(*) FROM ecs_goods e WHERE e.goods_id <= g.goods_id) AS rownum,

goods_id,

goods_name

FROM ecs_goods g

ORDER BY 1;

3、from后的子查询

子查询返回的结果当做数据源来使用.

语法:

#单表

select list from tab_name ....

select list from (select expression) alias_name ... #MySQL内联视图必须有别名

#连接

select list

from left_tab join_type right_tab

on join_condition ...

select list

from (select expression) alias_name join_type (select expression) alias_name

on join_condition ...

#哪些用户购买了市场价格大于2000的商品

SELECT * FROM ecs_users;

SELECT * FROM ecs_order_info;

SELECT * FROM ecs_order_goods;

#SELECT * FROM ecs_goods;

SELECT u.user_id, u.user_name, t.goods_name, t.market_price

FROM(

ecs_users u

INNER JOIN ecs_order_info oi

ON u.user_id = oi.user_id

)INNER JOIN(SELECT * FROM ecs_order_goods og

WHERE og.market_price > 2000) t

ON oi.order_id = t.order_id;

4、where后的子查询

○ 比较谓词中的子查询

where ve1 VS ve2

#ve1 or ve2 可以使用 select expression 替换

where ve VS (select expression)

#找出市场价格与P806相同的商品信息

SELECT *

FROM ecs_goods

WHERE market_price = (SELECT market_price FROM ecs_goods WHERE goods_name = 'P806');

▲ Subquery returns more than 1 row错误

原因: 子查询返回的行数>=2

SELECT *

FROM ecs_goods

WHERE market_price = (SELECT market_price FROM ecs_goods WHERE brand_id = 1);

规避: 让子查询返回的行数<=1

SELECT *

FROM ecs_goods

WHERE market_price = (SELECT market_price FROM ecs_goods WHERE brand_id = 1 limit 0,1);

▲ limit子句

语法:

limit [offset,]row_count

limit row_count OFFSET offset

其中,offset为偏移量,可以认为是从多少行以后开始取记录,若不写则默认为0

row_count为获取的行数

例子:

limit 0,1 #获取第一行

limit 5,8 #从第5行后面开始取,总共获取8行,即返回6-13行

limit 5 #获取前5行

○ 集合成员谓词中的子查询

where ve [not] in (ve1,ve2,...,ven)

#(ve1,ve2,...,ven) 可以使用 select expression 代替

#其本质上就是一个n行1列的表

where ve [not] in (select expression)

#哪些商品被客户购买过?

SELECT * FROM ecs_goods;

SELECT * FROM ecs_order_goods;

SELECT *

FROM ecs_goods

WHERE goods_id IN (SELECT goods_id FROM ecs_order_goods);

#哪些商品没有被客户购买过?

SELECT *

FROM ecs_goods

WHERE goods_id NOT IN (SELECT goods_id FROM ecs_order_goods);

▲ not in陷阱

原因: not in后的集合中包含了null元素

#更改并更新品牌表

ALTER TABLE ecs_goods MODIFY brand_id SMALLINT(5) UNSIGNED NULL;

UPDATE ecs_goods

SET brand_id = NULL

WHERE brand_id = 9;

COMMIT;

#商品品牌表中有哪些品牌没有出现在商品表中

SELECT * FROM ecs_brand;

SELECT * FROM ecs_goods;

SELECT *

FROM ecs_brand

WHERE brand_id NOT IN (SELECT brand_id FROM ecs_goods);

WHERE bi NOT IN (1,2,3,4,NULL) -->

WHERE NOT bi IN (1,2,3,4,NULL) -->

WHERE NOT (bi = 1 OR bi = 2 OR bi = 3 OR bi = 4 OR bi = NULL) -->

WHERE (bi != 1 AND bi != 2 AND bi != 3 AND bi != 4) AND bi != NULL -->

(TRUE OR FALSE OR unknown) AND unknown --> unknown or false 恒为假

规避: 去掉not in后集合中的null元素

SELECT *

FROM ecs_brand

WHERE brand_id NOT IN (SELECT brand_id FROM ecs_goods WHERE brand_id IS NOT NULL);

○ 存在谓词中的子查询

where [not] exists (select expression)

#select expression 返回 非空集 表示存在 exists谓词返回 true

#select expression 返回 空集 表示不存在 exists谓词返回 false

#哪些商品被客户购买过?

SELECT * FROM ecs_goods;

SELECT * FROM ecs_order_goods;

SELECT *

FROM ecs_goods g

WHERE EXISTS (SELECT * FROM ecs_order_goods

WHERE goods_id = g.goods_id);

#哪些产品没有被客户购买过?

SELECT *

FROM ecs_goods g

WHERE NOT EXISTS (SELECT * FROM ecs_order_goods

WHERE goods_id = g.goods_id);

▲ 关联子查询与非关联子查询

#非关联子查询

子查询能够独立运行返回一个结果

父查询不需要向子查询传递数据

SELECT * FROM ecs_goods

WHERE shop_price > (SELECT shop_price FROM ecs_goods

WHERE goods_name = '诺基亚E66');

#关联子查询

子查询不能够独立运行,

需要父查询逐行向其传递数据

SELECT *

FROM ecs_goods g

WHERE EXISTS (SELECT * FROM ecs_order_goods

WHERE goods_id = g.goods_id);

相关文章

网友评论

      本文标题:MySQL | 数据查询语言之子查询

      本文链接:https://www.haomeiwen.com/subject/vgrfyrtx.html