首页 > 数据库 > SQL Server > 正文

详解SQL嵌套子查询

2024-08-31 00:46:50
字体:
来源:转载
供稿:网友

一些初级程序员常常对SQL语法中的子查询,由其对嵌套子查询(子查询中包含一个子查询)的使用比较生疏,本文就此做一个基本讲解,相信新手会有一定收获。
    使用子查询的原则
 
1.一个子查询必须放在圆括号中。 
  2.将子查询放在比较条件的右边以增加可读性。 
子查询不包含 ORDER BY 子句。对一个 SELECT 语句只能用一个 ORDER BY 子句, 
并且如果指定了它就必须放在主 SELECT 语句的最后。  
ORDER BY 子句可以使用,并且在进行 Top-N 分析时是必须的。 
  3.在子查询中可以使用两种比较条件:单行运算符和多行运算符。 

    子查询的类型 
单行子查询:从内 SELECT 语句只返回一行的查询 
多行子查询:从内 SELECT 语句返回多行的查询 

    单行子查询 
单行子查询是从内查询返回一行的查询。在该子查询类型中用一个单行操作符。幻灯片中列出了单行操作符。 

显示那些 job ID 与雇员 141 相同的雇员。 
SELECT last_name, job_id 
FROM employees 
WHERE job_id = 
(SELECT job_id 
FROM employees 
WHERE employee_id = 141); 

SELECT last_name, job_id, salary 
FROM employees 
WHERE job_id = 
(SELECT job_id 
FROM employees 
WHERE employee_id = 141) 
AND salary > 
(SELECT salary 
FROM employees 
WHERE employee_id = 143); 

显示 job ID 与雇员 141 相同,并且薪水 高于雇员 143 的那些雇员。 

注:外和内查询可以从不同的表中取得数据。 

SELECT last_name, job_id, salary 
FROM employees 
WHERE salary = 
(SELECT MIN(salary) 
FROM employees); 

求所有人谁的工资最小。 

SELECT department_id, MIN(salary) 
FROM employees 
GROUP BY department_id 
HAVING MIN(salary) > 
(SELECT MIN(salary) 
FROM employees 
WHERE department_id = 50); 

求每个部门的最小工资,但是要高于50号部门的工资。 

SELECT employee_id, last_name 
FROM employees 
WHERE salary = 
(SELECT MIN(salary) 
FROM employees 
GROUP BY department_id); 

问题出现在:单行子查询返回了多个查询值; 
应改为: 
SELECT employee_id, last_name 
FROM employees 
WHERE salary in 
(SELECT MIN(salary) 
FROM employees 
GROUP BY department_id);

SELECT last_name, job_id 
FROM employees 
WHERE job_id = 
(SELECT job_id 
FROM employees 
WHERE last_name = ’Haas’); 

如果子查询返回的是零值,不会对主程序造成影响; 
如果子查询返回的是空值,那么会影响主程序的返回值; 
SELECT employee_id, 
last_name 
FROM employees 
WHERE employee_id NOT IN 
(SELECT manager_id 
FROM employees) 

SELECT employee_id, 
last_name 
FROM employees 
WHERE employee_id NOT IN 
(SELECT manager_id 
FROM employees 
WHERE manager_id IS NOT NULL) 

放在select下的子查询的返回值必须是一个具体值, 
from后面也可以加子查询; 
having后面也可以加子查询; 
order by后面也可以; 

 

多列子查询适应于:成对比较;非成对比较。  

SELECT employee_id, manager_id, department_id  
FROM employees  
WHERE (manager_id, department_id) IN  
(SELECT manager_id, department_id  
FROM employees  
WHERE employee_id IN (178,174))  
AND employee_id NOT IN (178,174);  

输出:176 149 80  

只有要查询的东西和你子查询返回的东西一一对应上了,你的查询才能成功。  
如果有一个 对应不上那么你的查询不会成功。  

非成对的子查询:  
SELECT employee_id, manager_id, department_id  
FROM employees  
WHERE manager_id IN (SELECT manager_id  
FROM employees  
WHERE employee_id IN (174,141))  
AND department_id IN (SELECT department_id  
FROM employees  
WHERE employee_id IN (174,141))  
AND employee_id NOT IN(174,141);  

输出:144 124 50  
143 124 50  
142 124 50  
176 149 80  
上面两个程序就是成对子查询和非成对子查询两者之间的区别。  

如果我想去显示员工信息,要求:员工的工资高于本部门的平均工资。  
SELECT a.last_name,  
a.salary,  
a.department_id  
FROM employees a  
WHERE a.salary >  
(SELECT AVG(salary)  
FROM employees b  
WHERE b.department_id = a.department_id);  

in line view(内联视图)  

SELECT a.last_name, a.salary,  
a.department_id, b.salavg  
FROM employees a, (SELECT department_id,  
AVG(salary) salavg  
FROM employees  
GROUP BY department_id) b  
WHERE a.department_id = b.department_id  
AND a.salary > b.salavg;


数据分散于多个表中需要进行拼合
SELECT DISTINCT c.LastName, c.FirstName 
FROM Person.Contact c JOIN HumanResources.Employee e
ON e.ContactID = c.ContactID WHERE EmployeeID IN 
(SELECT SalesPersonID 
FROM Sales.SalesOrderHeader
WHERE SalesOrderID IN 
(SELECT SalesOrderID 
FROM Sales.SalesOrderDetail
WHERE ProductID IN 
(SELECT ProductID 
FROM Production.Product p 
WHERE ProductNumber LIKE 'FW123%')));

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表