Sei sulla pagina 1di 10

SkillSoft Learning Object

Page 1 of 10

| Print | Contents | Close |

Advanced subqueries in Oracle9i databases


Learning objective

After completing this topic, you should be able to use the advanced functionality of subqueries in an Oracle9i database.

1. Multiple-column subqueries
Standard single-row and multiple-row subqueries return values from only one column. To return values from more than one column in a subquery, you need to use a multiplecolumn subquery. Multiple-column subqueries include compound WHERE clauses that combine multiple conditions into a single WHERE clause.

Main query WHERE (manager_id, department_id) IN Subquery manager_id department_id 100 90 102 60 124 50

For example, you can use a multiple-column subquery to compare the salary and job ID of every employee in a company against the salary and job ID of a specific employee or group of employees. You can construct
l l

pairwise multiple-column subqueries nonpairwise multiple-column subqueries

Pairwise multiple-column subqueries select multiple column values from the same row or group of rows.

SELECT employee_id, last_name ||','|| first_name AS "Employee", job_id, salary FROM employees WHERE (job_id, salary) IN (SELECT job_id, salary FROM employees WHERE employee_id=155) AND employee_id <> 155;

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 2 of 10

To construct a pairwise multiple-column subquery, you enclose the column names in the WHERE clause between parentheses and use a multiple-column SELECT statement as the subquery. In the example, the code will retrieve the details of all employees who have the same job ID and earn the same salary as employee number 155. iSQL*Plus evaluates the subquery, determines that employee 155 has a job ID of SA_REP and a salary of $7000, and displays rows for all other employees who have the same salary and job ID details. Nonpairwise multiple-column subqueries can select different column values from different rows, so the column queries they include don't need to be related.

SELECT employee_id, last_name||','||first_name AS "Employee", job_id, salary FROM employees WHERE job_id IN (SELECT job_id FROM employees FROM employee_id=155) AND salary IN (SELECT salary FROM employees WHERE employee_id=120) AND employee_id NOT IN (155, 120);

To construct a nonpairwise multiple-column subquery, you create two WHERE statements joined by an AND operator and you place single-column subqueries in each of the WHERE statements. In this example, the code will retrieve the details of all employees who have the same job ID as employee number 155 and the same salary as employee number 120. iSQL*Plus evaluates the subquery, determines that employee 155 has a job ID of SA_REP and that employee 120 has a salary of $8000, and displays rows for all other employees whose details match the query conditions. You can use a multiple-column subquery in the FROM clause of a SELECT statement. This generates results similar to a customized view, so these subqueries are called inline views.

SELECT e.employee_id, e.last_name, e.job_id, e.commission_pct, c.averagecomm FROM employees e, (SELECT job_id, AVG(commission_pct) AS averagecomm FROM employees GROUP BY job_id) c WHERE e.job_id = c.job_id AND e.commission_pct > c.averagecomm;

To use a subquery in the FROM clause of a SELECT statement, you write the statement as if the results of the subquery were a second table. You assign names to both the queried table and the subquery results and then you perform a join between the table and

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object


the subquery results.

Page 3 of 10

In this example, the query will retrieve the details of all employees whose commission percentage is higher than the average commission percentage for their job roles. The subquery in the FROM statement creates an inline view that contains the average commission percentage for each job role. iSQL*Plus displays the employees' names, job IDs, and commission percentages, along with the average commission percentage of their job roles as calculated by the subquery.

2. Scalar subquery expressions


Scalar subqueries are simple subqueries that return a single column value from one row. You can include scalar subqueries in any clause of a SELECT statement except in a GROUP BY clause.

Question

Where apart from in SELECT statements do you think you can use scalar subqueries? Options: 1. 2. 3. 4. In CASE statements In HAVING clauses In RETURNING clauses In UPDATE statements

Answer

You can include scalar subqueries in CASE and UPDATE statements but not in HAVING or RETURNING clauses.

You cannot use scalar subqueries in START WITH and CONNECT BY clauses or in statements such as CREATE PROFILE statements that are unrelated to queries. Furthermore, you cannot use scalar subqueries as the basis for function-based indexes or as default values for columns or hash expressions for clusters. The example shows a scalar subquery in the WHEN condition of a CASE statement. This query lists the status of all employees, assigning "Chief Executive Officer" status to the president and "Staff" status to everyone else.

SELECT first_name, last_name (CASE

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 4 of 10

WHEN job_id= (SELECT job_id FROM jobs WHERE job_title='President') THEN 'Chief Executive Officer' ELSE 'Staff' END) AS Status FROM employees;

iSQL*Plus first evaluates the subquery, which returns the row that includes the "President" job ID. The CASE statement then assigns the "Chief Executive Officer" job status to the company president and the "Staff" status to all other employees.

3. Correlated subqueries
A correlated subquery is a subquery that refers to a column from a parent query and performs a comparative operation on the value of that column in each row that the parent query retrieves. iSQL*Plus first selects a row using the parent query and then executes the subquery using a column value from the selected row. Because correlated subqueries execute once for each row that the parent query selects, they can return a different result for each row. To write a correlated subquery, you assign an alias to the table to which the parent query refers to distinguish it from the table to which the subquery refers. Because the queries can refer to the same table, you need to make a clear distinction. In this example, you use the alias "e" for the employees table.

SELECT employee_id, last_name, commission_pct, job_id FROM employees e WHERE commission_pct > (SELECT AVG(commission_pct) FROM employees WHERE job_id=e.job_id);

For each employee, the subquery calculates the average commission percentage of all employees in the same job role and then compares this average against the commission percentage of the currently selected employee. This query returns details of employees whose commission percentage is higher than the average commission percentage for their job roles. You can use any logical operator in the comparison clause of a correlated subquery. This includes the IN, ANY, and ALL operators, as well as the <, =, >, and <> operators.

4. Correlated UPDATE and DELETE statements


You can use correlated subqueries in UPDATE and DELETE statements.

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 5 of 10

In an UPDATE statement, a correlated subquery updates rows in one table using data from rows in another table. You need to place the subquery in the SET clause of the UPDATE statement. Let's say that you have added a column named max_salary to the employees table. Now you need to populate this column with data from the max_salary column of the jobs table.

ALTER TABLE employees ADD (max_salary NUMBER);

To do this, you write an UPDATE statement that includes a correlated subquery. The subquery retrieves each employee's maximum salary from the jobs table and the UPDATE statement assigns this value to the max_salary column in the employees table.

UPDATE employees e SET max salary= (SELECT max_salary FROM jobs j WHERE e.job_id=j.job_id);

You can use a correlated subquery to delete rows selectively by using it in the WHERE clause of a DELETE statement.

DELETE FROM departments d WHERE d.department_id NOT IN (SELECT e.department_id FROM employees e WHERE d.department_id = e.department_id);

This statement deletes all departments from the departments table that do not have any employees working in them. The DELETE statement selects rows from the departments table. The subquery searches the employee table for employees working in each department. If the subquery returns no results for a row, the DELETE statement deletes the current row.

Question

In the code statement displayed, which line, if any, will cause an error? UPDATE marketing SET temp_salary = (SELECT AVG(salary)FROM employees); Options: 1. (SELECT AVG(salary)FROM employees); 2. SET temp_salary = 3. There are no errors

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 6 of 10

Answer

There are no errors in the code. Option 1 is incorrect. This line of code will successfully return the average salary earned from the employees table. Option 2 is incorrect. The SET command is used in the UPDATE statement to specify the name of the column that is to by updated, in this case, temp_salary. Option 3 is correct. This statement will process the second part of the statement first. First, it will find the average salary from the employees table. Then the UPDATE statement identifies the table to be updated, in this case, marketing and the SET command specifies the column to update, temp_salary. If the subquery fails, the update will not take place.

5. The EXISTS and NOT EXISTS operators


In addition to conventional logical operators, you can use EXISTS and NOT EXISTS operators in conjunction with correlated subqueries. These operators test whether a correlated subquery returns any results. In this example, the parent query searches the departments table. The subquery selects employees who are members of each currently selected department. The EXISTS operator tests whether the subquery returns any results.

SELECT department_id, department_name FROM departments d WHERE EXISTS (SELECT e.department_id FROM employees e WHERE e.department_id= d.department_id);

The query uses the EXISTS operator to return a list only of departments that currently have employees working in them and to exclude departments that do not have employees. When you substitute a NOT EXISTS operator for an EXISTS operator, you obtain the opposite results to those obtained by the EXISTS query.

SELECT department_id, department_name FROM departments d WHERE NOT EXISTS (SELECT e.department_id FROM employees e WHERE e.department_id=

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 7 of 10

d.department_id);

For example, this query returns a list of all departments that do not have employees working for them.

6. The WITH clause


WITH clauses also called subquery factoring clauses allow you to save the results of a subquery temporarily. A statement can then access these stored results as often as necessary.

SELECT department_id, department_name FROM departments d WHERE NOT EXISTS (SELECT e.department_id FROM employees e WHERE e.department_id= d.department_id);

iSQL*Plus processes the subquery specified in a WITH clause only once and then saves the results. This improves performance, especially in the case of subqueries that require intensive processing each time they execute. You can use WITH clauses only in SELECT statements. You enter the WITH clause before the SELECT statement because iSQL*Plus needs to evaluate this clause before it can execute the statement.

WITH salary_costs AS (SELECT department_name, SUM(salary) salary_total FROM employees e JOIN departments d ON e.department_id=d.department_id GROUP BY department_name), average_salary AS (SELECT SUM(salary_total)/COUNT (*) AS average FROM salary_costs) SELECT * FROM salary_costs WHERE salary_total < (SELECT average FROM average_salary) ORDER BY department_name;

You can define and name more than one subquery result set in a single WITH clause. To do this, you separate the subqueries using commas. The result set of a subquery in a WITH clause is available to any subqueries that you've defined subsequently in the WITH clause, as well as to the main query. Let's say you want to know which departments pay their staff a total combined salary that is lower than the average total salary per department. This requires iSQL*Plus repeatedly to execute a complex subquery that uses a table join to calculate the total salary for a department.

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 8 of 10

WITH salary_costs AS (SELECT department_name, SUM(salary) salary_total FROM employees e JOIN departments d ON e.department_id=d.department_id GROUP BY department_name), average_salary AS (SELECT SUM(salary_total)/COUNT (*) AS average FROM salary_costs) SELECT * FROM salary_costs WHERE salary_total < (SELECT average FROM average_salary) ORDER BY department_name;

To improve performance, you place this subquery in a WITH clause, along with the subquery that calculates the average total salary. The second subquery and the parent query both refer to the first subquery. iSQL*Plus evaluates the subqueries in the WITH statement first and then uses the main query to return a list of all staff whose salaries are below their departmental average.

Question

Which of these statements about advanced subqueries in Oracle9i are correct? Options: 1. You can use correlated subqueries in SELECT statements but not in UPDATE or DELETE statements. 2. You can use EXISTS and NOT EXISTS operators in conjunction with correlated subqueries 3. You can use scalar subqueries in START WITH and CONNECT BY clauses. 4. You can use WITH clauses only in SELECT statements

Answer

You can use WITH clauses only in SELECT statements and you can use EXISTS and NOT EXISTS operators in conjunction with correlated subqueries. Option 1 is incorrect. You can use correlated subqueries in UPDATE statements to update one table with values from another table and in DELETE statements to delete rows that meet specific conditions. Option 2 is correct. These operators test whether a correlated subquery returns any results. Option 3 is incorrect. You cannot use scalar subqueries as the basis for functionbased indexes or as default values for columns or hash expressions for clusters.

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 9 of 10

Option 4 is correct. You enter the WITH clause before the SELECT statement because iSQL*Plus needs to evaluate this clause before it can execute the statement.

Summary
Multiple-column subqueries return values from more than one column by including compound WHERE clauses that combine multiple conditions into a single WHERE clause. Comparison can be pairwise or nonpairwise. You can include subqueries in the FROM clause of a SELECT statement to produce an inline view. You can include scalar subqueries subqueries that return one value only as part of expressions in CASE, DECODE, and UPDATE statements. You can also use scalar subquery expressions in any part of a SELECT statement except in a GROUP BY clause. Correlated subqueries are subqueries that perform an operation on each row that a parent query selects. You can therefore use correlated subqueries to perform comparisons against each row of the table to which a parent query refers. You can use correlated subqueries in UPDATE statements to update one table with values from another table and in DELETE statements to delete rows that meet specific conditions. You can use the EXISTS and NOT EXISTS operators to determine whether a subquery has returned any results. WITH clauses allow you to store the results of complex subqueries so that a parent query or subsequent subqueries can use the results. Because Oracle needs to execute the subqueries once only, the use of WITH clauses improves performance.

Table of Contents
| Top of page | | Learning objective | | 1. Multiple-column subqueries | | 2. Scalar subquery expressions | | 3. Correlated subqueries | | 4. Correlated UPDATE and DELETE statements | | 5. The EXISTS and NOT EXISTS operators | | 6. The WITH clause | | Summary |

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

SkillSoft Learning Object

Page 10 of 10

Copyright 2003 SkillSoft. All rights reserved. SkillSoft and the SkillSoft logo are trademarks or registered trademarks of SkillSoft in the United States and certain other countries. All other logos or trademarks are the property of their respective owners.

http://xlibrary.skillport.com/courseware/cbtlib/66925/68145/eng/thin/transcript.html

5/11/2007

Potrebbero piacerti anche