你真的会玩SQL吗?系列目录
子查询又称内部,而包含子查询的语句称之外部查询(又称主查询)。
所有的子查询可以分为两类,即相关子查询和非相关子查询
1> 非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询。
2> 相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。
故非相关子查询比相关子查询效率高
--非相关子查询
SELECT EMPNO, LASTNAME
FROM EMPLOYEE
WHERE WORKDEPT = 'A00'
AND SALARY > (SELECT AVG(SALARY)
FROM EMPLOYEE
WHERE WORKDEPT = 'A00')
--相关子查询
SELECT E1.EMPNO, E1.LASTNAME, E1.WORKDEPT
FROM EMPLOYEE E1
WHERE SALARY > (SELECT AVG(SALARY)
FROM EMPLOYEE E2
WHERE E2.WORKDEPT = E1.WORKDEPT)
ORDER BY E1.WORKDEPT
所有的子查询可以分为两类,即相关子查询和非相关子查询
1> 非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询。
2> 相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。
故非相关子查询比相关子查询效率高
--非相关子查询
SELECT EMPNO, LASTNAME
FROM EMPLOYEE
WHERE WORKDEPT = 'A00'
AND SALARY > (SELECT AVG(SALARY)
FROM EMPLOYEE
WHERE WORKDEPT = 'A00')
--相关子查询
SELECT E1.EMPNO, E1.LASTNAME, E1.WORKDEPT
FROM EMPLOYEE E1
WHERE SALARY > (SELECT AVG(SALARY)
FROM EMPLOYEE E2
WHERE E2.WORKDEPT = E1.WORKDEPT)
ORDER BY E1.WORKDEPT
子查询
嵌套子查询,非相关子查询
相关子查询
自联接
联合查询
•Union 操作符:将两个或更多个 SELECT 语句的结果合并为一个结果集。
•联合可以指定为如下形式:
SELECT 语句 UNION [ALL] SELECT 语句
使用 ALL 子句表示不删除重复的行。
联合查询注意事项:
- 每个select必须具有相同的列结构
- 兼容列类型(指优先级较低数据类型必须能隐式地转换为较高级的数据类型)和相同数目的列
练习:
使用子查询
/*1:写一条查询语句,返回Orders表中活动的最后一天生成的所有订单。 涉及的表:Sales.Orders表。 期望的输出:*/ orderid orderdate custid empid ----------- ----------------------- ----------- ----------- 11077 2008-05-06 00:00:00.000 65 1 11076 2008-05-06 00:00:00.000 9 4 11075 2008-05-06 00:00:00.000 68 8 11074 2008-05-06 00:00:00.000 73 7
参考SQL:
--answer: select orderid,orderdate,custid,empid from Sales.Orders where orderdate in ( select max(orderdate) from Sales.Orders ) /* 1.处理嵌套在外层查询语句里的子查询,应用max函数从表Sales.Orders中查找orderdate最后一天的日期,生成虚拟表VT1, 2.处理嵌套在外层的查询语句,从Sales.Orders表中查找满足where条件orderdate在虚拟表VT1中有相等值的数据,得到虚拟表VT2 3.处理select列表,从虚拟表VT2中查找出custid,orderdate,custid,empid返回虚拟表VT3 */
/*2:写一条查询语句,并返回2008年5月1号(包括这一天)以后没有处理过的订单的雇员。 涉及到表:HR.Employees表和Sales.Orders表。 期望的输出:*/ empid FirstName lastname ----------- ---------- -------------------- 3 Judy Lew 5 Sven Buck 6 Paul Suurs 9 Zoya Dolgopyatova
参考SQL:
--answer: select empid,firstname,lastname from HR.Employees where empid not in( select o.empid from Sales.Orders as o where o.orderdate>='2008-05-01' ) /* 1.处理嵌套在外层查询语句里的子查询,表Sales.Orders别名o 2.查找满足where条件 o.orderdate>='2008-05-01',生成虚拟表VT1 3.从虚拟表VT1中处理select列表,查找出empid生成虚拟表VT2 4.处理嵌套在外层的查询语句,从Sales.Orders表中查找满足where条件empid不在虚拟表VT2中有相等值的数据,得到虚拟表VT3 5.处理select列表从虚拟表VT3中查找empid,firstname,lastname返回虚拟表VT4 */
/*3:写一条查询语句,返回订购了第12号产品的客户。 涉及的表:Sales.Customers表和Sales.Orders表。 期望的输出:*/ custid companyname ---------------------------------------- 48 Customer DVFMB 39 Customer GLLAG 71 Customer LCOUJ 65 Customer NYUHS 44 Customer OXFRU 51 Customer PVDZC 86 Customer SNXOJ 20 Customer THHDP 90 Customer XBBVR 46 Customer XPNIK 31 Customer YJCBX 87 Customer ZHYOS
参考SQL:
--answer: SELECT custid, companyname FROM Sales.Customers AS C WHERE EXISTS (SELECT * FROM Sales.Orders AS O WHERE O.custid = C.custid AND EXISTS (SELECT * FROM Sales.OrderDetails AS OD WHERE OD.orderid = O.orderid AND OD.ProductID = 12)); /* 1.先处理外层查询,从Sales.Customers表别名C中取出一个元组,将元组相关列值custid传给内层查询 2.执行第一层内层查询,Sales.Orders表别名O中取出一个元组,将元组相关列值custid传给内层查询 3.执行第二层内层查询,Sales.Orders表别名OD应用where子句返回满足条件OD.orderid = O.orderid和 OD.ProductID = 12的值 4.返回到第一层内层查询中,应用where子句返回满足条件O.custid = C.custid和EXISTS条件的值 5.返回到外层查询处理 EXISTS,外查询根据子查询返回的结果集得到满足条件的行 */