sql⼦查询嵌套SELECT实⽤语句
嵌套SELECT语句也叫⼦查询,⼀个 SELECT 语句的查询结果能够作为另⼀个语句的输⼊值。⼦查询不但能够出现在Where⼦句中,也能够出现在from⼦句中,作为⼀个临时表使⽤,也能够出现在select list中,作为⼀个字段值来返回。
1、单⾏⼦查询 :单⾏⼦查询是指⼦查询的返回结果只有⼀⾏数据。当主查询语句的条件语句中引⽤⼦查询结果时可⽤单⾏⽐较符号(=, >,<, >=, <=, <>)来进⾏⽐较。
例:
select ename,deptno,sal from emp
where deptno=(select deptno from dept where loc='NEW YORK');
2、多⾏⼦查询:多⾏⼦查询即是⼦查询的返回结果是多⾏数据。当主查询语句的条件语句中引⽤⼦查询结果时必须⽤多⾏⽐较符号(IN,ALL,ANY)来进⾏⽐较。其中,IN的含义是匹配⼦查询结果中的任⼀个值即可(\"IN\" 操作符,能够测试某个值是否在⼀个列表
中),ALL则必须要符合⼦查询的所有值才可,ANY要符合⼦查询结果的任何⼀个值即可。⽽且须注意ALL 和ANY 操作符不能单独使⽤,⽽只能与单⾏⽐较符(=、>、< 、>= 、<= 、<>)结合使⽤。例:
1).多⾏⼦查询使⽤IN操作符号例⼦:查询选修了⽼师名叫Rona(假设唯⼀)的学⽣名字sql> select stNamefrom Student
where stId in(selectdistinct stId from score where teId=(select teId from teacher where teName='Rona')); 查询所有部门编号为A的资料:SELECT ename,job,salFROM EMP
WHERE deptno in ( SELECT deptno FROM dept WHERE dname LIKE 'A%');
2).多⾏⼦查询使⽤ALL操作符号例⼦:查询有⼀门以上的成绩⾼于Kaka的最⾼成绩的学⽣的名字:sql> select stNamefrom Student
where stId in(select distinct stId from score where score >all(select score from score where stId=(select stId from Student where stName='Kaka') ));
3). 多⾏⼦查询使⽤ANY操作符号例⼦:查询有⼀门以上的成绩⾼于Kaka的任何⼀门成绩的学⽣的名字:sql> select stNamefrom Student
where stId in(select distinct stId from score where score >any(select score from score where stId=(select stId from Student wherestName='Kaka')));
3、多列⼦查询:当是单⾏多列的⼦查询时,主查询语句的条件语句中引⽤⼦查询结果时可⽤单⾏⽐较符号(=, >, <, >=, <=, <>)来进⾏⽐较;当是多⾏多列⼦查询时,主查询语句的条件语句中引⽤⼦查询结果时必须⽤多⾏⽐较符号(IN,ALL,ANY)来进⾏⽐较。例:
SELECT deptno,ename,job,sal FROM EMP
WHERE (deptno,sal) IN (SELECT deptno,MAX(sal) FROM EMP GROUP BY deptno); 4、内联视图⼦查询
例:
(1)SELECT ename,job,sal,rownum
FROM (SELECT ename,job,sal FROM EMP ORDER BY sal); (2)SELECT ename,job,sal,rownum
FROM ( SELECT ename,job,sal FROM EMP ORDER BY sal) WHERE rownum<=5; 5、在HAVING⼦句中使⽤⼦查询例:
SELECT deptno,job,AVG(sal) FROM EMP GROUP BY deptno,job HAVING AVG(sal)>(SELECT sal FROM EMP WHEREename='MARTIN');
让我们再看看⼀些具体的实例,
⼀、给出⼈⼝多于Russia()的国家名称
SELECT name FROM bbcWHERE population>
(SELECT population FROM bbcWHERE name='Russia')
⼆、给出'India'(印度), 'Iran'(伊朗)所在地区的任何国家的任何信息
SELECT * FROM bbcWHERE region IN
(SELECT region FROM bbcWHERE name IN ('India','Iran'))
三、给出⼈均GDP超过'United Kingdom'(英国)的欧洲国家.
SELECT name FROM bbc
WHERE region='Europe' AND gdp/population >(SELECT gdp/population FROM bbcWHERE name='United Kingdom')
查考资料:sql⼦查询总结:
许多包含⼦查询的 Transact-SQL 语句都可以改⽤联接表⽰。在 Transact-SQL 中,包含⼦查询的语句和语义上等效的不包含⼦查询的语句在性能上通常没有差别。但是,在⼀些必须检查存在性的情况中,使⽤联接会产⽣更好的性能。否则,为确保消除重复值,必须为外部查询的每个结果都处理嵌套查询。所以在这些情况下,联接⽅式会产⽣更好的效果。以下⽰例显⽰了返回相同结果集的Select⼦查询和Select联接:
Select Name
FROM AdventureWor ks.Production.Product Where ListPrice = (Select ListPrice
FROM AdventureWor ks.Production.Product Where Name = ’Chainring Bolts’ )
Select Prd1. Name
FROM AdventureWor ks.Production.Product AS Prd1 JOIN AdventureWor ks.Production.Product AS Prd2 ON (Prd1.ListPrice = Prd2.ListPrice) Where Prd2. Name = ’Chainring Bolts’
嵌套在外部Select语句中的⼦查询包括以下组件: ●包含常规选择列表组件的常规Select查询。
●包含⼀个或多个表或视图名称的常规 FROM ⼦句。●可选的 Where ⼦句。
●可选的 GROUP BY ⼦句。●可选的 HAVING ⼦句。
⼦查询的Select查询总是使⽤圆括号括起来。它不能包含COMPUTE 或 FOR BROWSE ⼦句,如果同时指定了 TOP ⼦句,则只能包含 orDER BY ⼦句。
⼦查询可以嵌套在外部 Select,Insert,Update 或 Delete语句的 Where 或 HAVING ⼦句内,也可以嵌套在其他⼦查询内。尽管根据可⽤内存和查询中其他表达式的复杂程度的不同,嵌套也有所不同,但嵌套到 32 层是可能的。个别查询可能不⽀持 32 层嵌套。任何可以使⽤表达式的地⽅都可以使⽤⼦查询,只要它返回的是单个值。
如果某个表只出现在⼦查询中,⽽没有出现在外部查询中,那么该表中的列就⽆法包含在输出(外部查询的选择列表)中。
包含⼦查询的语句通常采⽤以下格式中的⼀种:
●Where expression [NOT] IN (subquery)
●Where expression comparison_operator [ANY | ALL] (subquery) ●Where [NOT] EXISTS (subquery)
在某些 Transact-SQL 语句中,⼦查询可以作为独⽴查询来计算。从概念上说,⼦查询结果会代⼊外部查询(尽管这不⼀定是 Microsoft SQLServer 2005 实际处理带有⼦查询的 Transact-SQL 语句的⽅式)。有三种基本的⼦查询。它们是:
●在通过 IN 或由 ANY 或 ALL 修改的⽐较运算符引⼊的列表上操作。●通过未修改的⽐较运算符引⼊且必须返回单个值。●通过 EXISTS 引⼊的存在测试。1.带in的嵌套查询
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal in (select sal from scott.emp where ename=’’WARD’’); 上述语句完成的是查询薪⽔和WARD相等的员⼯,也可以使⽤not in来进⾏查询。
2.带any的嵌套查询
通过⽐较运算符将⼀个表达式的值或列值与⼦查询返回的⼀列值中的每⼀个进⾏⽐较,只要有⼀次⽐较的结果为TRUE,则ANY测试返回TRUE。
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >any(select sal from scott.emp where job=’’MANAGER’’); 等价于下边两步的执⾏过程:
(1)执⾏“select sal from scott.emp where job=’’MANAGER’’”
(2)查询到3个薪⽔值2975、2850和2450,⽗查询执⾏下列语句:
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >2975 or sal>2850 or sal>2450;
3.带some的嵌套查询
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal =some(select sal from scott.emp where job=’’MANAGER’’);等价于下边两步的执⾏过程:
(1)⼦查询,执⾏“select sal from scott.emp where job=’’MANAGER’’”。(2)⽗查询执⾏下列语句。
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal =2975 or sal=2850 or sal=2450;
带【any】的嵌套查询和【some】的嵌套查询功能是⼀样的。早期的SQL仅仅允许使⽤【any】,后来的版本为了和英语的【any】相区分,引⼊了【some】,同时还保留了【any】关键词。
4.带all的嵌套查询
通过⽐较运算符将⼀个表达式的值或列值与⼦查询返回的⼀列值中的每⼀个进⾏⽐较,只要有⼀次⽐较的结果为FALSE,则ALL测试返回FALSE。
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >all(select sal from scott.emp where job=’’MANAGER’’); 等价于下边两步的执⾏过程:
(1)⼦查询,执⾏“select sal from scott.emp where job=’’MANAGER’’”。(2)⽗查询执⾏下列语句。
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp where sal >2975 and sal>2850 and sal>2450;5.带exists的嵌套查询
select emp.empno,emp.ename,emp.job,emp.sal from scott.emp,scott.dept where exists (select * from scott.emp wherescott.emp.deptno=scott.dept.deptno);6.并操作的嵌套查询
并操作就是集合中并集的概念。属于集合A或集合B的元素总和就是并集。 (select deptno from scott.emp) union (select deptno from scott.dept); 7.交操作的嵌套查询
交操作就是集合中交集的概念。属于集合A且属于集合B的元素总和就是交集。 (select deptno from scott.emp) intersect (select deptno from scott.dept);
8.差操作的嵌套查询
差操作就是集合中差集的概念。属于集合A且不属于集合B的元素总和就是差集。(select deptno from scott.dept) minus (select deptno from scott.emp);
注意:并、交和差操作的嵌套查询要求属性具有相同的定义,包括类型和取值范围。
左⼿边是⼀个标量表达式列表.右⼿边可以是⼀个等长的标量表达式的列表, 或者⼀个圆括弧括起来的⼦查询,该查询必须返回很左⼿边表达式书⽬完全 ⼀样的字段.另外,该⼦查询不能返回超过⼀⾏的数量.(如果它返回零⾏, 那么结果就是 NULL.)左⼿边逐⾏与右⼿边的⼦查询结果⾏,或者右⼿边 表达式列表进⾏⽐较.⽬前,只允许使⽤ = 和 <> 操作符进⾏逐⾏⽐较. 如果两⾏分别是相等或者不等,那么结果为真.
通常,表达式或者⼦查询⾏⾥的 NULL 是按照 SQL 布尔表达式的⼀般规则 进⾏组合的.如果两个⾏对应的成员都是⾮空并且相等,那么认为这两⾏ 相等;如果任意对应成员为⾮空且不等,那么该两⾏不等; 否则这样的⾏⽐较的结果是未知(NULL).