Oracle DB 使用子查询来解决查询
2017-07-03 18:37
441 查看
• 定义子查询
• 描述子查询可以解决的问题类型
• 列出子查询的类型
• 编写单行和多行子查询
• 子查询:类型、语法和准则
• 单行子查询:
– 子查询中的组函数
– 带有子查询的HAVING子句
• 多行子查询
– 使用ALL或ANY运算符
• 使用EXISTS运算符
• 子查询中的空值
- 使用子查询解决问题
- 子查询语法
SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table);
子查询是一个SELECT语句,它嵌入到另一个SELECT语句的子句中。通过使用子查询,可以用简单的语句构建功能强大的语句。当需要从表中选择行,而选择条件却取决于该表自身中的数据时,子查询非常有用。 可以在许多SQL 子句中使用子查询,其中包括以下子句: • WHERE子句 • HAVING子句 • FROM子句 在该语法中: operator包括比较条件,例如>、=或IN 注:比较条件分为以下两类:单行运算符(>、=、>=、<、<>、<=)和多行运算符(IN、ANY、ALL、EXISTS)。 子查询通常被称为嵌套SELECT语句、子SELECT语句或内部SELECT语句。通常先执行子查询,然后使用其输出来完善主查询(即外部查询)的查询条件。
- 使用子查询
SELECT last_name, salary FROM employees WHERE salary > (SELECT salary FROM employees WHERE last_name = 'Abel');
在示例中,内部查询确定了雇员Abel 的薪金。外部查询会采用内部查询的结果并根据此结果显示薪金超过雇员Abel 的所有雇员。
- 使用子查询的准则
- 子查询的类型
- 单行子查询
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 last_name= 'Taylor') AND salary > (SELECT salary FROM employees WHERE last_name= 'Taylor');
可以将SELECT语句看作一个查询块。示例显示其职务与Taylor 相同但薪金高于Taylor 的雇员。 该示例由三个查询块组成:一个外部查询和两个内部查询。先执行内部查询块,生成的查询结果分别为SA_REP和8600。然后可以处理外部查询块,使用内部查询返回的值来完善其搜索条件。 两个内部查询都返回单个值(分别为SA_REP和8600),因此将此SQL 语句称为单行子查询。 注:外部查询和内部查询可以从不同的表中获得数据。
- 在子查询中使用组函数
SELECT last_name,job_id, salary FROM employees WHERE salary = (SELECT MIN(salary) FROM employees);
通过在子查询中使用组函数来返回单行,可以从主查询中显示数据。子查询包含在括号中,位于比较条件之后。 示例显示其薪金等于最低薪金的所有雇员的姓氏、职务ID 和薪金。MIN组函数将单个值(2500) 返回给外部查询。
- 带有子查询的HAVING子句
SELECT department_id, MIN(salary) FROM employees GROUP BY department_id HAVING MIN(salary) > (SELECT MIN(salary) FROM employees WHERE department_id = 50);
不仅可以在WHERE子句中使用子查询,还可以在HAVING子句中使用子查询。Oracle 服务器会执行子查询,并将结果返回到主查询的HAVING子句中。 示例中的SQL 语句显示最低薪金高于部门50 的最低薪金的所有部门。 示例: 查找具有最低平均薪金的职务。
SELECT job_id, AVG(salary) FROM employees GROUP BY job_id HAVING AVG(salary) = (SELECT MIN(AVG(salary)) FROM employees GROUP BY job_id);
- 此语句中有什么错误
Connected. hr@TEST0924> SELECT employee_id, last_name FROM employees 2 WHERE salary = 3 (SELECT MIN(salary) FROM employees GROUP BY department_id); (SELECT MIN(salary) FROM employees GROUP BY department_id) * ERROR at line 3: ORA-01427: single-row subquery returns more than one row
子查询的常见错误是单行子查询返回了多行。 在示例的SQL 语句中,子查询包含一个GROUP BY子句,这意味着该子查询将返回多行,每行都对应于一个它找到的组。这种情况下,子查询的结果为4400、6000、 2500、4200、7000、17000和8300。 外部查询将采用这些结果,并在其WHERE子句中使用它们。该WHERE子句包含一个等于(=) 运算符,该运算符是一个只需要一个值的单行比较运算符。=运算符无法接受子查询中的多个值,因此产生了错误。 要更正此错误,请将=运算符更改为IN。
- 内部查询没有返回任何行
hr@TEST0924> SELECT last_name, job_id FROM employees 2 WHERE job_id = 3 (SELECT job_id FROM employees WHERE last_name = 'Haas');
no rows selected 子查询的另外常见问题是内部查询没有返回任何行。 在示例的SQL 语句中,子查询包含一个WHERE子句。据推测,该语句的目的是要查找名为Haas 的雇员。该语句正确,但是因为没有名为“Haas”的雇员,所以执行时没有选择任何行。因此,子查询不会返回任何行。 外部查询采用子查询的结果(空值),并在其WHERE子句中使用这些结果。外部查询没有找到职务ID 等于空值的雇员,因此不会返回任何行。即使存在值为空的职务,也不会返回行,因为两个空值的比较会产生一个空值,从而使WHERE条件不为“真”。
- 多行子查询
SELECT last_name, salary, department_id FROM employees WHERE salary IN (SELECT MIN(salary) FROM employees GROUP BY department_id);
示例: 查找其薪金等于各个部门最低薪金的雇员。 先执行内部查询,生成一个查询结果。然后可以处理主查询块,使用内部查询返回的值完善其搜索条件。事实上,主查询将以下面的形式出现在Oracle Server 上:
SELECT last_name, salary, department_id FROM employees WHERE salary IN (2500, 4200, 4400, 6000, 7000, 8300, 8600, 17000);
- 在多行子查询中使用ANY运算符
SELECT employee_id, last_name, job_id, salary FROM employees WHERE salary < ANY (SELECT salary FROM employees WHERE job_id = 'IT_PROG') AND job_id <> 'IT_PROG';
ANY运算符(及其同义词SOME运算符)用于将某个值与子查询返回的每个值进行比较。 示例显示不是IT 程序员且薪金低于任一IT 程序员的雇员。程序员的最高薪金为$9,000。 • <ANY表示低于最高值。 • >ANY表示高于最低值。 • =ANY等同于IN。 参考:https://www.geek-share.com/detail/2591080761.html
- 在多行子查询中使用ALL运算符
SELECT * FROM departments WHERE NOT EXISTS (SELECT * FROM employees WHERE employees.department_id=departments.department_id);
使用EXISTS运算符 在查询中使用EXISTS运算符,查询结果取决于某些行是否在表中存在。如果子查询至少返回一行,则求值结果为TRUE。 示例显示没有雇员的部门。对于DEPARTMENTS表中每一行,检查条件,看一看在EMPLOYEES表中是否存在具有相同部门ID 的行。如果不存在这样的行,则相应 行满足条件,从而选择该行。如果EMPLOYEES表中存在相应行,则不选择该行。
- 子查询中的空值
SELECT emp.last_name FROM employees emp WHERE emp.employee_id NOT IN (SELECT mgr.manager_id FROM employees mgr);
示例中的SQL 语句尝试显示没有任何下属的所有雇员。逻辑上,此SQL 语句应该返回12 行。但是,该SQL 语句没有返回任何行。因为内部查询返回的值中有一个为空值,所以整个查询不会返回任何行。 原因是所有条件与空值进行比较后都会产生一个空值。因此,只要子查询的结果集中可能包含空值,就不要使用NOT IN运算符。NOT IN运算符等同于<> ALL。 请注意,如果使用的是IN运算符,则子查询的结果集中存在空值就不会成为问题。IN运算符等同于=ANY。 例如,要显示具有下属的雇员,可以使用下面的SQL 语句:
SELECT emp.last_name FROM employees emp WHERE emp.employee_id IN (SELECT mgr.manager_id FROM employees mgr);
另外,可以在子查询中包括WHERE子句,用来显示没有下属的所有雇员:
SELECT last_name FROM employees WHERE employee_id NOT IN (SELECT manager_id FROM employees WHERE manager_id IS NOT NULL);
- 小结
相关文章推荐
- [转]Oracle DB 使用子查询来解决查询
- Oracle DB 使用子查询来解决查询
- 解决32位工具如何连接64位DB---Oracle Instant Client 使用 说明
- 解决在mybatis中使用CTE进行oracle查询数据类型为long的字段出现流关闭问题
- oracle 中通过使用客户端导致查询出来的中文数据为乱码的解决方式
- Oracle SQL使用笛卡尔连接、正则表达式和层次查询、union all、unpiovt 解决多列值筛选、列转行问题
- [DB][ORACLE][统计函数]使用LAG和LEAD函数可以在一次查询中取出同一字段的前N行的数据和后N行的值
- 解决在mybatis中使用CTE进行oracle查询数据类型为long的字段出现流关闭问题
- Oracle 数据库中在使用中文模糊查询时输入中文查询不到结果的解决方法
- 不能“在oracle db server上使用sqlplus / as sysdba”的解决办法
- "Microsoft OLE DB Provider for ODBC Drivers (0x80004005) 操作必须使用一个可更新的查询”错误的解决办法
- Oracle出现了问题“无法使用系统回滚段”并解决
- 解决使用ASP无法连接 ORACLE 9i 数据库的问题。
- oracle使用了索引但是查询性能没有改善(oracle的索引陷阱)
- Access中"操作必须使用一个可更新的查询"错误的解决办法
- 错误“操作必须使用一个可更新的查询”原因及解决办法
- 开始使用CodeSmith3.1-解决了Oracle连接及汉字的问题
- oracle使用了索引但是查询性能没有改善(oracle的索引陷阱)
- 如何解决ADO.NET访问Access数据库出现"操作必须使用一个可更新的查询"的问题
- ORACLE查询中出现“Ora-01791 不是Selected表达式”错误信息的解决办法