实例详解mysql子查询
子查询分类
按返回结果集分类
子查询按返回结果集的不同分为4种:表子查询,行子查询,列子查询和标量子查询。表子查询:返回的结果集是一个行的集合,N行N列(N>=1)。表子查询经常用于父查询的FROM子句中。行子查询:返回的结果集是一个列的集合,一行N列(N>=1)。行子查询可以用于福查询的FROM子句和WHERE子句中。列子查询:返回的结果集是一个行的集合,N行一列(N>=1)。标量子查询:返回的结果集是一个标量集合,一行一列,也就是一个标量值。可以指定一个标量表达式的任何地方,都可以用一个标量子查询。
从定义上讲,每个标量子查询也是一个行子查询和一个列子查询,反之则不是;每个行子查询和列子查询也是一个表子查询,反之也不是。
按照对返回结果的调用方法
子查询按对返回结果集的调用方法,可分为where型子查询,from型子查询及exists型子查询。
where型子查询:(把内层查询结果当作外层查询的比较条件)定义:where型的子查询就是把内层查询的结果当作外层查询的条件。from型子查询:(把内层的查询结果供外层再次查询)定义:from子查询就是把子查询的结果(内存里的一张表)当作一张临时表,然后再对它进行处理。exists型子查询:(把外层查询结果拿到内层,看内层的查询是否成立)定义:exists子查询就是对外层表进行循环,再对内表进行内层查询。和in()差不多,但是它们还是有区别的。主要是看两个张表大小差的程度。若子查询表大则用exists(内层索引),子查询表小则用in(外层索引);
使用子查询原则
1.一个子查询必须放在圆括号中。
2.将子查询放在比较条件的右边以增加可读性。子查询不包含ORDERBY子句。对一个SELECT语句只能用一个ORDERBY子句,并且如果指定了它就必须放在主SELECT语句的最后。
3.在子查询中可以使用两种比较条件:单行运算符(>,=,>=,<,<>,<=)和多行运算符(IN,ANY,ALL)。
实例分析
创建测试表
CREATETABLEPLAYERS (PLAYERNOINTEGERNOTNULL, NAMECHAR(15)NOTNULL, INITIALSCHAR(3)NOTNULL, BIRTH_DATEDATE, SEXCHAR(1)NOTNULL, JOINEDSMALLINTNOTNULL, STREETVARCHAR(30)NOTNULL, HOUSENOCHAR(4), POSTCODECHAR(6), TOWNVARCHAR(30)NOTNULL, PHONENOCHAR(13), LEAGUENOCHAR(4), PRIMARYKEY(PLAYERNO)); CREATETABLEPENALTIES (PAYMENTNOINTEGERNOTNULL, PLAYERNOINTEGERNOTNULL, PAYMENT_DATEDATENOTNULL, AMOUNTDECIMAL(7,2)NOTNULL, PRIMARYKEY(PAYMENTNO));
注:表players为球员信息基本表,表penalties为有过罚款记录的球员信息列表。
插入测试数据
INSERTINTOPLAYERSVALUES(2,'Everett','R','1948-09-01','M',1975,'StoneyRoad','43','3575NH','Stratford','070-237893','2411'); INSERTINTOPLAYERSVALUES(6,'Parmenter','R','1964-06-25','M',1977,'HaseltineLane','80','1234KK','Stratford','070-476537','8467'); INSERTINTOPLAYERSVALUES(7,'Wise','GWS','1963-05-11','M',1981,'EdgecombeWay','39','9758VB','Stratford','070-347689',NULL); INSERTINTOPLAYERSVALUES(8,'Newcastle','B','1962-07-08','F',1980,'StationRoad','4','6584WO','Inglewood','070-458458','2983'); INSERTINTOPLAYERSVALUES(27,'Collins','DD','1964-12-28','F',1983,'LongDrive','804','8457DK','Eltham','079-234857','2513'); INSERTINTOPLAYERSVALUES(28,'Collins','C','1963-06-22','F',1983,'OldMainRoad','10','1294QK','Midhurst','010-659599',NULL); INSERTINTOPLAYERSVALUES(39,'Bishop','D','1956-10-29','M',1980,'EatonSquare','78','9629CD','Stratford','070-393435',NULL); INSERTINTOPLAYERSVALUES(44,'Baker','E','1963-01-09','M',1980,'LewisStreet','23','4444LJ','Inglewood','070-368753','1124'); INSERTINTOPLAYERSVALUES(57,'Brown','M','1971-08-17','M',1985,'EdgecombeWay','16','4377CB','Stratford','070-473458','6409'); INSERTINTOPLAYERSVALUES(83,'Hope','PK','1956-11-11','M',1982,'MagdaleneRoad','16A','1812UP','Stratford','070-353548','1608'); INSERTINTOPLAYERSVALUES(95,'Miller','P','1963-05-14','M',1972,'HighStreet','33A','5746OP','Douglas','070-867564',NULL); INSERTINTOPLAYERSVALUES(100,'Parmenter','P','1963-02-28','M',1979,'HaseltineLane','80','6494SG','Stratford','070-494593','6524'); INSERTINTOPLAYERSVALUES(104,'Moorman','D','1970-05-10','F',1984,'StoutStreet','65','9437AO','Eltham','079-987571','7060'); INSERTINTOPLAYERSVALUES(112,'Bailey','IP','1963-10-01','F',1984,'VixenRoad','8','6392LK','Plymouth','010-548745','1319'); INSERTINTOPENALTIESVALUES(1,6,'1980-12-08',100); INSERTINTOPENALTIESVALUES(2,44,'1981-05-05',75); INSERTINTOPENALTIESVALUES(3,27,'1983-09-10',100); INSERTINTOPENALTIESVALUES(4,104,'1984-12-08',50); INSERTINTOPENALTIESVALUES(5,44,'1980-12-08',25); INSERTINTOPENALTIESVALUES(6,8,'1980-12-08',25); INSERTINTOPENALTIESVALUES(7,44,'1982-12-30',30); INSERTINTOPENALTIESVALUES(8,27,'1984-11-12',75);
表子查询实例
如:获取编号小于10的男性球员的号码
mysql>selectplayernofrom( selectplayerno,sex fromplayers whereplayerno<10) asplayers10wheresex='M';
行子查询实例
如:获取和100号球员性别相同并且居住在同一城市的球员号码。
mysql>selectplayerno fromplayers where(sex,town)=( selectsex,town fromplayers whereplayerno=100);
说明:子查询的结果是带有两个值的一行:('M','stratford')。这个值和一个行表达式(sex,town)进行比较。
标量子查询实例
可以指定一个标量表达式的任何地方,几乎都可以使用一个标量子查询。如:获取和27号球员出生在同一年的球员的号码
mysql>selectplayerno fromplayers whereyear(birth_date)= (selectyear(birth_date) fromplayers whereplayerno=27) andplayerno<>27;
上面语句等同于:
mysql>selectplayernofromplayerswhereyear(birth_date)=1964andplayerno<>27;
列子查询实例
由于列子查询返回的结果集是N行一列,因此不能直接使用=><>=<=<>这些比较标量结果的操作符。在列子查询中可以使用IN、ANY(SOME)和ALL操作符:IN:在指定项内,同IN(项1,项2,…)。ANY:与比较操作符联合使用,ANY关键字必须接在一个比较操作符的后面,表示与子查询返回的任何值比较为TRUE,则返回TRUE。SOME:ANY的别名,较少使用。ALL:与比较操作符联合使用,ALL关键字必须接在一个比较操作符的后面,表示与子查询返回的所有值比较都为TRUE,则返回TRUE。
实例1(in):获取球员性别为女的所有球员的球员号,名字及所在城市。
mysql>selectplayerno,name,town fromplayers whereplayernoin (selectplayerno fromplayers wheresex='F');
实例2(any):获取至少比同城的另一球员年轻的所有球员的号码,日期和居住城市。
mysql>selectplayerno,birth_date,town fromplayersasp1 wherebirth_date>any (selectbirth_date fromplayersasp2 wherep1.town=p2.town);
实例3(all):获取最老球员的号码,名字及生日。(即出生日期数值小于或等于所有其它球员的球员)
mysql>selectplayerno,name,birth_date fromplayers wherebirth_date<=all (selectbirth_date fromplayers);
XISTS关键字表示存在。使用EXISTS关键字时,内层查询语句不返回查询的记录,而是返回一个真假值,如果内层查询语句查询到满足条件的记录,只要子查询中至少返回一个值,则EXISTS语句的值就为True。就返回true,否则返回false。当返回的值为true时,外层查询语句将进行查询,否则不进行查询。NOTEXISTS刚好与之相反。exists的用法和in()差不多,但是它们还是有区别的。主要是看两个张表大小差的程度。若子查询表大则用exists(内层索引),子查询表小则用in(外层索引);
实例1(exists):获取那些至少支付了一次罚款的球员的名字和首字母。
mysql>selectname,initials fromplayers whereexists (select*frompenalties whereplayerno=players.playerno);
实例2(notexists):获取那些从来没有罚款的球员的名字和首字母。
mysql>selectname,initials fromplayers wherenotexists (select*frompenalties whereplayerno=players.playerno);
以上就是实例详解mysql子查询的详细内容,更多关于mysql子查询的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。