种地 发表于 2024-12-27 23:05:03

Mysq学习-Mysql查询(4)

5.子查询
子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL4.1开始引入.在SELECT子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表.
子查询中常用的操纵符有ANY(SOME),ALL,IN,EXISTS.子查询可以添加到SELECT,UPDATE和DELETE语句中,而且可以进行多层嵌套.子査询中也可以使用比较运算符,如"<""<=""!="等
下面将先容如何在SELECT语句中嵌套子查询.
(1)带ANY,SOME关键字的子查询
ANY和SOME关键字是同义词,表示满足其中任一条件,它们答应创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个比较条件,就返回一个结果作为外层查询的条件.
ANY关键字接在一个比较操纵符的背面,表示若与子查询返回的任何值比较为TRUE,则返回TRUE;
返回tbl2表的所有num2列,然后将tbl1中的num1的值与之进行比较,只要大于num2的任何1个值,即为符合查询条件的结果

SELECT num1
FROM tb11
WHERE num1 > ANY(SELECT num2 FROM tbl2); (2)带ALL关键字的子查询
ALL关键字与ANY和SOME不同,使用ALL时须要同时满足全部内层査询的条件,例如,修改前面的例子,用ALL关键字更换ANY.
ALL关键字接在一个比较操纵符的背面,表示与子査询返回的全部值比较为TRUE,则返回TRUE;
返回tbl1表中比tb12表num2列所有值都大的值
SELECT num1 FROM tbl1
WHERE num1 > ALL(SELECT num2 FROM tbl2); 在子査询中,返回的是tbl2表的全部num2列结果(6,14,11,20),然后将tbl1中的num1列的值与之进行比较,大于全部num2列值的num1值只有27,因此返回结果为27
(3)带EXISTS关键字的子查询
EXISTS关键字背面的参数是一个任意的子査询,系统对子查询进行运算以判定它是否返回行,如果至少返回一行,那么EXISTS的结果为true,此时外层査询语句将进行査询:如果子查询没有返回任何行,那么EXISTS返回的结果为false,此时外层语句将不进行查询,
查询suppliers表中是否存在s id=107的供应商,如果存在,则查询fruits表中的记录
SELECT *
from fruits
WHERE EXISTS
(SELECT s_name FROM suppliers WHERE s_id=107); EXISTS可以和条件表达式一起使用
查询suppliers表中是否存在s id=107的供应商,如果存在,则査询fruits表中的f price大于10.20的记录
SELECT *
FROM fruits
WHERE f_price>10.20 AND EXISTS
(SELECT s_name FROM suppliers WHERE s_id=107); 注意,内层查询结果为true才去执行外层的查询语句
NOT EXISTS与EXISTS使用方法相同,返回的结果相反.子査询如果至少返回一行,那么NOT EXISTS的结果为false,此时外层查询语句将不进行查询.如果子查询没有返回任何行,那么NOT EXISTS返回的结果为true,此时外层语句将进行查询,
查询suppliers表中是否存在s id=107的供应商,如果不存在则査询fruts表中的记录
SELECT *
FROM fruits
WHERE NOT EXISTS
(SELECT s_name FROM suppliers WHERE s_id=107); 查询语句SELECTs name FORM suppliers WHEREsid=107,对suppliers表进行查询返回了条记录,NOT EXISTS表达式返回false,外层表达式吸取false,将不再查询fruits表中的记录
注意:EXISTS和NOT EXISTS的结果只取决于是否会返回行,而不取决于这些行的内容,所以这个子查询输入列表通常是无关紧要的

(4)带IN关键字的子查询
IN关键字进行子查询时,内层查询语句仅仅返回一个数据列,这个数据列里的值将提供给外层查询语句进行比较操纵.
在orderitems表中查询f id为c0的订单号,并根据订单号查询具有订单号的客户cid;
SELECT c_id FROM orders
WHERE o_num IN
(SELECT o_num FROM orderitems WHERE f_id='c0'); 这个例子说明在处置惩罚SELECT语句的时间,MySQL现实上执行了两个操纵过程,即先执行内层子查询再执行外层查询,内层子查询的结果作为外部查询的比较条件:
SELECT语句中可以使用NOTIN关键字,其作用与IN恰恰相反
与前一个例子类似,但是在SELECT语句中使用NOT IN关键字:
SELECT c_id
FROM orders
WHERE o_num NOT IN
(SELECT o_num FROM orderitems WHERE f_id='c0'); 注意:子查询的功能也可以通过毗连查询完成,但是子查询使得MySQL代码更容易阅读和编写

(5)带比较运算符的子查询
在前面先容的带ANYALL关键字的子查询时使用了">"比较运算符,子查询时还可以使用其他的比较运算符,如"<""<="'>=""|="等
在suppliers表中査询s city等于"Tianjin"的供应商s id,然后在fruits表中查询所有该供应商提供的水果的种类;

SELECT s_id,f_name
FROM fruits
WHERE s_id =
(SELECT s1.s_id FROM suppliers AS s1 WHERE s1.s_city = 'Tianjin'); 6.归并查询结果
利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集,归并时,两个表对应的列数必须相同.各个SELECT语句之间使用UNION或UNION ALL关键字分隔.UNION不使用关键字ALL,执行的时间删除重复的记录,全部返回的行都是唯一的;使用关键字ALL的作用是不删除重复行也不对结果进行自动排序.
归并结果集在数据库查询中非常有效,尤其是在处置惩罚多表查询或须要对多个查询结果进行组适时。归并结果集可以做到:数据整合.简化查询逻辑.提高性能.机动性和可扩展性
须要注意的是,归并结果集时,被归并的两个结果的列数、列类型必须相同。如果列类型不相同,可以通过SELECT关键字去筛选须要的列,以确保归并操纵的正确性。
查询所有价格小于9的水果的信息,査询s_id等于101和103所有水果的信息,使用UNION连接查询结果;
SELECT s_id,f_name,f_price
FROM fruits
WHERE f_price <9.0
UNION SELECT s_id,f_name,f_price
FROM fruits
WHERE s_id IN(101,103);
//返回12行 使用UNION ALL包罗重复的行,在前面的例子中,分开查询时,两个返回结果中有相同的记录.UNION从查询结果集中自动去除了重复的行,如果要返回全部匹配行,而不进行删除,可以使用UNION ALL.
注意:UNION和UNION ALL的区别:使用UNION ALL的功能时不删除重复行,加上ALL关键字语句执行时所须要的资源少,所以尽可能地使用它,因此知道有重复行但是想保留这些行,确定查询结果中不会有重复数据或者不须要去掉重复数据的时间,应当使用UNION ALL以提高查询服从
在大部分情况下,UNION ALL的服从要高于UNION。这是因为UNION在进行表毗连后会筛选掉重复的记录,这个过程涉及到排序运算和删除重复记录的操纵,相对较为耗时。而UNION ALL只是简单地将两个结果归并后就返回,不会进行去重和排序操纵,因此执行速率更快。总之,在选择使用UNION还是UNION ALL时,应综合考虑业务需求、数据特点以及性能要求等因素,以选择最得当的操纵符。
7.为表和字段取别名
在前面先容分组查询,集合函数查询和嵌套子查询章节中,实在我们有的地方已经使用了AS关键字为查询结果中的某一列指定一个特定的名字.在内毗连查询时,则对相同的表fruits分别指定两个不同的名字,这里可以为字段或者表取一个别名,在查询时,使用别名替代其指定的内容
(1)为表取别名
当表名字很长或者执行一些特别查询时,为了方便操纵或者须要多次使用相同的表时,可以为表指定别名,用这个别名替代原来的名称.
为orders表取别名o,查询30001订单的下单日期;
SELECT *
FROM orders As o
WHERE o.o_num=30001; 为customers和orders表分别取别名,并进行连接查询;(左连接)
SELECT c.c_id,o.o_num
FROM customers AS c LEFT OUTER JOIN orders AS o
ON c.c_id = o.c_id; 由结果看到,MySQL可以同时为多个表取别名,而且表别名可以放在不同的位置,如WHERE子句,SELECT列表,ON子句以及ORDER BY子句等
在前面先容内毗连查询时指出自毗连是一种特别的内毗连,在毗连查询中的两个表都是同一个表,其查询语句如下:
SELECT f1.f_id,f1.f_name
FROM fruits AS fl,fruits AS f2
WHERE f1.s_id =f2.s_id AND f2.f_id ='a1'; 在这里,如果不使用表别名,MySQL将不知道引用的是哪个fruits表实例,这是表别名一个非常有效的地方.
在为表取别名时,要保证不能与数据库中其他表的名称辩论

(2)为字段取别名
在使用SELECT语句表现查询结果时,MVSQL会表现每个SELECT背面指定的输出列,在有些情况下表现的列的名称会很长或者名称不够直观,MySQL可以指定列别名,更换字段或表达式.
查询fruits表中,为f_name取别名fruit_name,f_price取别名fruits,为fruits表取别名f1,查询表中f price<8的水果的名称;
SELECT f1.f_name As fruits_name,f1.f_price As fruit_price
FROM fruits AS f1
MWHERE f1.f_price<8; 也可以为SELECT子句中的计算字段取别名,例如,对使用COUNT聚合函数或者CONCAT等系统函数执行的结果字段取别名
查询suppliers表中字段s name和s city,使用CONCAT函数连接这两个字段值,并取列别名为suppliers title.
SELECT CONCAT(TRIM(s_name),'(',TRIM(s_city)')')
As suppliers_title
FROM suppliers
ORDER BY s_name; 由结果可以看到,SELECT子句计算字段值之后增加了AS suppliers title,它指示MySQL为计算字段创建一个别名suppliers title,表现结果为指定的列别名,这样就增强了查询结果的可读性
注意:表别名只在执行查询的时间使用,并不在返回结果中表现;而列别名界说之后,将返回给客户端表现,表现的结果字段为字段列的别名,

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Mysq学习-Mysql查询(4)