Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Subqueries These slides are licensed under.

Similar presentations


Presentation on theme: "1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Subqueries These slides are licensed under."— Presentation transcript:

1 1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Subqueries These slides are licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. For more information on how you may use them, please see http://www.openlineconsult.com/db

2 2 © Ellis Cohen 2001-2008 Overview of Lecture Scalar Subqueries Vector Subqueries Subqueries and View Modification Correlated Scalar Subqueries Complex Correlated Subqueries Correlated Subqueries and Grouping Correlated Updates & Deletes ANY & ALL Existence & Non-Existence

3 3 © Ellis Cohen 2001-2008 Scalar Subqueries

4 4 © Ellis Cohen 2001-2008 Scalar Subqueries SELECT ename, job, sal FROM Emps WHERE sal > (SELECT avg(sal) FROM Emps) Whose salaries are greater than the average salary? Calculate average salary: SELECT avg(sal) FROM Emps 2073.21 Whose salaries are greater? SELECT ename, job, sal FROM Emps WHERE sal > 2073.21 Scalar: result has one row & one column

5 5 © Ellis Cohen 2001-2008 Projection Scalar Subqueries SELECT ename, abs( sal - (SELECT avg(sal) FROM Emps) ) FROM Emps For each employee, how much is their salary different from the average salary? SELECT avg(sal) FROM Emps 2073.21 SELECT ename, abs(sal-2073.21) FROM Emps Scalar: result has one row & one column

6 6 © Ellis Cohen 2001-2008 Subquery Sites SELECT ename, job, sal, sal - (SELECT avg(sal) FROM Emps) AS diffsal FROM Emps Projection: For each employee, list their name, job, salary, and the difference between their salary and the average sal SELECT job FROM Emps GROUP BY job HAVING avg(sal) > (SELECT avg(sal) FROM Emps) Group Restriction: List the jobs whose average salary is larger than the overall average salary Restriction: List the name, job & salary of employees who make more than the average salary SELECT ename, job, sal FROM Emps WHERE sal > (SELECT avg(sal) FROM Emps) SELECT ename, job, sal FROM Emps ORDER BY abs(sal - (SELECT avg(sal) FROM Emps)) Ordering: List the name, job & salary of all employees, ordered by how close their salary is to the average salary

7 7 © Ellis Cohen 2001-2008 Subqueries are Not Needed SELECT ename, sal FROM Emps WHERE sal > (SELECT avg(sal) FROM Emps) How would you write this without a subquery (using views & joins)? SQL is a rich language in which there are many ways to do the same thing. In particular, every query written using a subquery can be written in SQL without using a subquery (using grouping, joins, views & collection operators)

8 8 © Ellis Cohen 2001-2008 Scalar Subqueries vs. Joins SELECT ename, sal FROM Emps WHERE sal > (SELECT avg(sal) FROM Emps) WITH AvgSalView AS (SELECT avg(sal) AS avgsal FROM Emps) SELECT ename, job, sal FROM (Emps JOIN AvgSalView ON sal > avgsal) empno ename deptno sal 7499ALLEN301600 7839KING105000 7844TURNER301500 7986STERN501500 join the Emps table with the average salary 3200 avgsal AvgSalView

9 9 © Ellis Cohen 2001-2008 Vector Subqueries

10 10 © Ellis Cohen 2001-2008 Vector Subqueries SELECT ename FROM Emps WHERE empno IN (SELECT pmgr FROM Projs) List the names of project managers Which employees are project managers? SELECT DISTINCT pmgr FROM Projs List the names of those employees SELECT ename FROM Emps WHERE empno IN ( 7566, 7698, 7782 ) PMGR ------ 7566 7698 7698 7782 7782 Vector: result has one column Why is DISTINCT not necessary? Can this be written without a subquery?

11 11 © Ellis Cohen 2001-2008 Vector Subqueries vs. Joins SELECT DISTINCT ename FROM (Emps JOIN Projs ON empno = pmgr) SELECT ename FROM Emps WHERE empno IN (SELECT pmgr FROM Projs) List the names of project managers

12 12 © Ellis Cohen 2001-2008 Vector Subquery Problem List the names of all the employees whose department is located in Boston SELECT ename FROM (Emps NATURAL JOIN Depts) WHERE loc = 'BOSTON' Redo as a subquery HINT: SELECT ename FROM Emps WHERE …

13 13 © Ellis Cohen 2001-2008 Vector Subqueries Answer SELECT ename FROM Emps WHERE deptno IN (SELECT deptno FROM Depts WHERE loc = 'BOSTON') List the names of all the employees whose department is located in Boston Which departments are located in Boston? SELECT deptno FROM Depts WHERE loc = 'BOSTON' List employees of those departments: SELECT ename FROM Emps WHERE deptno IN ( 42, 73 ) DEPTNO ------ 42 73 73 Vector: result has one column

14 14 © Ellis Cohen 2001-2008 Intersect and Subquery SELECT empno FROM MyEmps INTERSECT SELECT empno FROM YourEmps Find an equivalent way to write this using a subquery (and no joins) instead of INTERSECT You can assume empno is the primary key of both MyEmps and YourEmps

15 15 © Ellis Cohen 2001-2008 Intersect and Subquery SELECT empno FROM MyEmps INTERSECT SELECT empno FROM YourEmps SELECT empno FROM MyEmps WHERE empno IN (SELECT empno FROM YourEmps) What's the equivalent of SELECT empno FROM MyEmps EXCEPT SELECT empno FROM YourEmps

16 16 © Ellis Cohen 2001-2008 Except and Subquery SELECT empno FROM MyEmps EXCEPT SELECT empno FROM YourEmps SELECT empno FROM MyEmps WHERE empno NOT IN (SELECT empno FROM YourEmps)

17 17 © Ellis Cohen 2001-2008 Subqueries and View Modification

18 18 © Ellis Cohen 2001-2008 View Modification Using Subqueries UPDATE SomeEmpView SET sal = sal *1.1 WHERE job = 'DEPTMGR' Sometimes, the definition of a view may be too complex to allow it to be modified directly. In that case, a subquery can be used to constrain the update (or delete) based on the tuples in the view UPDATE Emps SET sal = sal *1.1 WHERE job = 'DEPTMGR' AND empno IN (SELECT empno FROM SomeEmpView)

19 19 © Ellis Cohen 2001-2008 View Modification Problem CREATE VIEW EmpDeptView AS SELECT * FROM (Emps NATURAL JOIN Depts) WHERE sal > 1500 UPDATE EmpDeptView SET sal = sal *1.1 WHERE loc = 'BOSTON' updates sal from Emps who have sal > 1500 and whose department is located in Boston Even though this view can be updated directly, rewrite the update in the form UPDATE Emps SET sal = sal * 1.1 WHERE …

20 20 © Ellis Cohen 2001-2008 Inefficient use of Subqueries UPDATE Emps SET sal = sal * 1.1 WHERE empno IN (SELECT empno FROM EmpDeptView WHERE loc = 'BOSTON') However, this may have poor performance unless the optimizer is extremely good, since it requires looking through the employees table Is there a better solution?

21 21 © Ellis Cohen 2001-2008 Modification with Subqueries UPDATE Emps SET sal = sal * 1.1 WHERE sal > 1500 AND deptno IN (SELECT deptno FROM Depts WHERE loc = 'BOSTON') This also gives you some idea of how clever the optimizer needs to be in order to process queries that modify view or that use subqueries

22 22 © Ellis Cohen 2001-2008 Correlated Scalar Subqueries

23 23 © Ellis Cohen 2001-2008 Queries as Loops select e.ename from Emps e where e.sal > 1500 empno ename deptno sal comm 7499ALLEN301600300 7654MARTIN3012502500 7698BLAKE302850 7839KING105000 7844TURNER3015000 7986STERN501500 Emps e Implementation: Cursor (named e) loops through each tuple of Emps, checking whether e.sal > 1500...... cursor

24 24 © Ellis Cohen 2001-2008 Queries with Referents What's the meaning of SELECT dname from Depts d WHERE d.deptno = 30 Suppose x had the value 30. What's the meaning of SELECT dname from Depts d WHERE d.deptno = x Suppose e were an employee in dept 30. What's the meaning of SELECT dname from Depts d WHERE d.deptno = e.deptno

25 25 © Ellis Cohen 2001-2008 Joins as Nested Loops empno ename deptno sal comm 7499ALLEN301600300 7654MARTIN3012502500 7698BLAKE302850 7839KING105000 7844TURNER3015000 7986STERN501500 Emps 10ACCOUNTING 30SALES 50SUPPORT deptno dname Depts SELECT ename, dname FROM Emps e, Depts d WHERE (e.sal > 1700) AND (d.deptno = e.deptno) Implementation: Emps' cursor e loops through each tuple of Emps, checking whether sal > 1700. Each time it finds such a tuple, Depts' cursor d loops through Depts, looking for a deptno that matches the deptno value in the Emps tuple referenced by e....... e d

26 26 © Ellis Cohen 2001-2008 Correlated Subqueries Correlated Subqueries correspond directly to nested loops SELECT ename, (SELECT dname FROM Depts d WHERE d.deptno = e.deptno) FROM Emps e WHERE sal > 1700 Is equivalent to SELECT ename, dname FROM Emps e, Depts d WHERE sal > 1700 AND d.deptno = e.deptno if every employees is assigned to a department Correlated subquery: the subquery references a cursored tuple of the outer query

27 27 © Ellis Cohen 2001-2008 Joins vs Subqueries? How do these differ if some employee is not assigned to a department? SELECT ename, (SELECT dname FROM Depts d WHERE d.deptno = e.deptno) FROM Emps e SELECT ename, dname FROM Emps e, Depts d WHERE d.deptno = e.deptno

28 28 © Ellis Cohen 2001-2008 Joins vs Subqueries SELECT ename, dname FROM Emps NATURAL JOIN Depts No tuples for unassigned employees A tuple for every employee. If an employee is not assigned to a department, the associated dname returned will be NULL SELECT ename, (SELECT dname FROM Depts d WHERE d.deptno = e.deptno) FROM Emps e What join is equivalent to the subquery?

29 29 © Ellis Cohen 2001-2008 Subqueries and Outer Joins SELECT ename, dname FROM Emps NATURAL LEFT JOIN Depts SELECT ename, (SELECT dname FROM Depts d WHERE d.deptno = e.deptno) FROM Emps e Instead, how would you change the subquery to make it equivalent to the inner join? Equivalent

30 30 © Ellis Cohen 2001-2008 Joins vs Subqueries with Restriction SELECT ename, (SELECT dname FROM Depts d WHERE d.deptno = e.deptno) FROM Emps e WHERE deptno IS NOT NULL Equivalent SELECT ename, dname FROM Emps NATURAL JOIN Depts

31 31 © Ellis Cohen 2001-2008 Correlated vs Uncorrelated Subqueries SELECT empno FROM Emps WHERE deptno IN (SELECT deptno FROM Depts WHERE loc = 'BOSTON') SELECT empno FROM Emps e WHERE (SELECT loc FROM Depts d WHERE e.deptno = d.deptno) = 'BOSTON' List the names of all the employees whose department is located in Boston

32 32 © Ellis Cohen 2001-2008 Complex Correlated Subqueries

33 33 © Ellis Cohen 2001-2008 Correlated Aggregate Subqueries with Complex Equivalent Joins List the names of employees whose salary is less than the average for their job SELECT ename FROM Emps e1 WHERE sal < (SELECT avg(sal) FROM Emps e2 WHERE e2.job = e1.job) Write an equivalent query using a join and a factored view This is a simple aggregate query. No GROUP BY!

34 34 © Ellis Cohen 2001-2008 Subqueries vs Views + Joins SELECT ename FROM Emps e1 WHERE sal < (SELECT avg(sal) FROM Emps WHERE e2.job = e1.job) Emps empno ename job sal … job jobsal AvgJobSals Average salary per job WITH AvgJobSals AS (SELECT job, avg(sal) AS jobsal FROM Emps GROUP BY job) SELECT ename FROM (Emps NATURAL JOIN AvgJobSals) WHERE sal < jobsal List the names of employees whose salary is less than the average for their job <

35 35 © Ellis Cohen 2001-2008 Self Joins vs Subqueries? Provides the names of employees who make less than their department manager SELECT e.ename FROM (Emps e JOIN Emps m ON e.deptno = m.deptno AND e.sal < m.sal) WHERE m.job = 'DEPTMGR' Write this using a subquery. Hint: SELECT ename FROM Emps e WHERE sal < (the subquery)

36 36 © Ellis Cohen 2001-2008 Equivalent Subquery Provides the name of employees who make less than their department manager SELECT ename FROM Emps e WHERE sal < (SELECT sal FROM Emps m WHERE m.job = 'DEPTMGR' AND m.deptno = e.deptno) How about the name & department name of those employees. Only use subqueries, but no joins!

37 37 © Ellis Cohen 2001-2008 Multiple Subqueries Provides the name & department name of employees who make less than their department manager SELECT ename, (SELECT dname FROM Depts d WHERE d.deptno = e.deptno) FROM Emps e WHERE sal < (SELECT sal FROM Emps m WHERE m.job = 'DEPTMGR' AND m.deptno = e.deptno)

38 38 © Ellis Cohen 2001-2008 Correlated Vector Subqueries Provides the name of employees who were hired before their manager SELECT ename FROM Emps e WHERE hiredate < (SELECT hiredate FROM Emps m WHERE m.empno = e.mgr) SELECT ename FROM Emps e WHERE mgr IN (SELECT empno FROM Emps m WHERE e.hiredate < m.hiredate)

39 39 © Ellis Cohen 2001-2008 Nested Subqueries List the names of projects whose budgets are larger than the total salaries of the employees in the project manager's department SELECT pname FROM Projs p WHERE p.budget > (SELECT sum(sal) FROM Emps e WHERE e.deptno = (SELECT deptno FROM Emps m WHERE m.empno = p.pmgr))

40 40 © Ellis Cohen 2001-2008 Scoping SELECT pname FROM Projs p WHERE p.budget > (SELECT sum(sal) FROM Emps e WHERE e.deptno = (SELECT deptno FROM Emps m WHERE m.empno = p.pmgr)) A subquery can only refer to table aliases of queries in which it is nested Can refer to p Can refer to p and e

41 41 © Ellis Cohen 2001-2008 Subqueries Can Often Replace Joins SELECT pname, dname FROM Projs p, (Emps e NATURAL JOIN Depts) WHERE p.pmgr = e.empno SQL is a rich language in which there are many ways to do the same thing. In particular, many queries written using a join can be written in SQL without using a join, but using subqueries Write this without joins using nested subqueries

42 42 © Ellis Cohen 2001-2008 Subqueries Not Joins SELECT pname, (SELECT dname FROM Depts d WHERE p.pmgr IN (SELECT empno FROM Emps e WHERE e.deptno = d.deptno)) FROM Projs p

43 43 © Ellis Cohen 2001-2008 Correlated Subqueries and Grouping

44 44 © Ellis Cohen 2001-2008 Replacing GROUPing by Subqueries Assume that every department has employees Write this (using a subquery) without using GROUP BY Hint: SELECT d.deptno, ( the subquery ) FROM Depts d SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP BY deptno

45 45 © Ellis Cohen 2001-2008 Replacing GROUPing by Subqueries SELECT deptno, (SELECT avg(sal) FROM Emps e WHERE e.deptno = d.deptno) AS avgsal FROM Depts d SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP by deptno These are equivalent ONLY if every department has employees. How do they differ if there are empty departments? Write it correctly using subqueries! This is a simple aggregate query. No GROUP BY!

46 46 © Ellis Cohen 2001-2008 Using Renaming Restrictions SELECT deptno, (SELECT avg(sal) FROM Emps e WHERE e.deptno = d.deptno) AS avgsal FROM Depts d WHERE avgsal IS NOT NULL SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP by deptno Departments without employees will be included with avgsal of NULL Only works in DBs like SQL Server, where renamed expression can be used in the query. How else could you solve the problem in Oracle?

47 47 © Ellis Cohen 2001-2008 Solution Using Restriction SELECT deptno, (SELECT avg(sal) FROM Emps e WHERE e.deptno = d.deptno) AS avgsal FROM Depts d WHERE (SELECT count(*) FROM Emps e WHERE e.deptno = d.deptno) > 0 SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP by deptno

48 48 © Ellis Cohen 2001-2008 Solution Finding Non-Empty Depts WITH EmpDepts AS (SELECT DISTINCT deptno FROM Emps) SELECT deptno, (SELECT avg(sal) FROM Emps e WHERE e.deptno = d.deptno) AS avgsal FROM EmpDepts d SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP by deptno

49 49 © Ellis Cohen 2001-2008 Group with Having Write this (using a subquery) without using GROUP BY or views Hint: SELECT deptno, … FROM Depts WHERE … SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP BY deptno HAVING count(*) > 2

50 50 © Ellis Cohen 2001-2008 Having using Restriction SELECT deptno, (SELECT avg(sal) FROM Emps e WHERE e.deptno = d.deptno) AS avgsal FROM Depts d WHERE (SELECT count(*) FROM Emps e WHERE e.deptno = d.deptno) > 2 SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP by deptno HAVING count(*) > 2

51 51 © Ellis Cohen 2001-2008 Correlated Updates & Deletes

52 52 © Ellis Cohen 2001-2008 Correlated Delete Delete every employee whose salary is the max salary for their department DELETE Emps e1 WHERE sal = (SELECT max(sal) FROM Emps e2 WHERE e2.deptno = e1.deptno) Can this be done without using a correlated delete? Hint: DELETE Emps WHERE empno IN …

53 53 © Ellis Cohen 2001-2008 Non-Correlated Delete Delete every employee whose salary is the max salary for their department DELETE Emps WHERE empno IN (SELECT empno FROM Emps e1 WHERE sal = (SELECT max(sal) FROM Emps e2 WHERE e2.deptno = e1.deptno) But this is way more complicated than DELETE Emps e1 WHERE sal = (SELECT max(sal) FROM Emps e2 WHERE e2.deptno = e1.deptno)

54 54 © Ellis Cohen 2001-2008 Correlated Update Increase the salaries of employees whose salary is less than their department manager's salary UPDATE Emps e SET sal = sal * 1.1 WHERE sal < (SELECT m.sal FROM Emps m WHERE m.job = 'DEPTMGR' AND m.deptno = e.deptno) How would you increase the salary of employees whose salary is less than the average for their job?

55 55 © Ellis Cohen 2001-2008 Correlated Where Clause Increase the salaries of employees whose salary is less than the average for their job UPDATE Emps e1 SET sal = sal * 1.1 WHERE sal < (SELECT avg(sal) FROM Emps e2 WHERE e2.job = e1.job) How about setting every employee's salary to the average salary of their department?

56 56 © Ellis Cohen 2001-2008 Correlated Set Clause Set every employee's salary to the average salary for their department UPDATE Emps e1 SET sal = (SELECT avg(sal) FROM Emps e2 WHERE e2.deptno = e1.deptno) How about setting an employee's salary to the average salary of their department only if their salary is less than the average salary

57 57 © Ellis Cohen 2001-2008 Correlated Set & Where Clauses UPDATE Emps e1 SET sal = (SELECT avg(sal) FROM Emps e2 WHERE e2.deptno = e1.deptno) WHERE sal < (SELECT avg(sal) FROM Emps e2 WHERE e2.deptno = e1.deptno)

58 58 © Ellis Cohen 2001-2008 Updates Using Views CREATE VIEW AvgDeptSals AS (SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP BY deptno) UPDATE Emps e SET sal = (SELECT avgsal FROM AvgDeptSals a WHERE a.deptno = e.deptno) WHERE sal < (SELECT avgsal FROM AvgDeptSals a WHERE a.deptno = e.deptno)

59 59 © Ellis Cohen 2001-2008 Updates Through Views CREATE VIEW AvgDeptSals AS (SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP BY deptno) CREATE VIEW EmpAvgView AS (SELECT * FROM Emps NATURAL JOIN AvgDeptSals) UPDATE EmpAvgView SET sal = avgsal WHERE sal < avgsal However, doesn't work in Oracle because definition of EmpAvgView uses AvgDeptSals which uses GROUP BY

60 60 © Ellis Cohen 2001-2008 Updates Using MERGE (10g) CREATE VIEW AvgDeptSals AS (SELECT deptno, avg(sal) AS avgsal FROM Emps GROUP BY deptno) MERGE INTO Emps e USING AvgDeptSals a ON (e.deptno = a.deptno AND e.sal < a.avgsal) WHEN MATCHED THEN UPDATE SET sal = a.avgsal

61 61 © Ellis Cohen 2001-2008 ANY & ALL

62 62 © Ellis Cohen 2001-2008 ANY Subqueries Provides the names of employees whose manager was hired after they were SELECT ename FROM Emps e WHERE mgr IN (SELECT empno FROM Emps m WHERE e.hiredate < m.hiredate) SELECT ename FROM Emps e WHERE mgr = ANY (SELECT empno FROM Emps m WHERE e.hiredate < m.hiredate)

63 63 © Ellis Cohen 2001-2008 ANY Comparisons List the names of employees hired after some clerk in their department SELECT ename FROM Emps e WHERE hiredate > ANY (SELECT hiredate FROM Emps c WHERE e.deptno = c.deptno AND c.job = 'CLERK') SELECT ename FROM Emps e WHERE hiredate > (SELECT min(hiredate) FROM Emps c WHERE e.deptno = c.deptno AND c.job = 'CLERK')

64 64 © Ellis Cohen 2001-2008 ALL Comparisons List the names of employees hired after every clerk in their department SELECT ename FROM Emps e WHERE hiredate > ALL (SELECT hiredate FROM Emps c WHERE e.deptno = c.deptno AND c.job = 'CLERK') SELECT ename FROM Emps e WHERE hiredate > (SELECT max(hiredate) FROM Emps c WHERE e.deptno = c.deptno AND c.job = 'CLERK')

65 65 © Ellis Cohen 2001-2008 ALL Equals List the names of departments where all employees are clerks SELECT dname FROM Depts d WHERE 'CLERK' = ALL (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) SELECT dname FROM Depts d WHERE (SELECT count(*) FROM Emps e WHERE d.deptno = e.deptno) = (SELECT count(*) FROM Emps e WHERE e.job = 'CLERK' AND d.deptno = e.deptno) What happens if a department has no employees?

66 66 © Ellis Cohen 2001-2008 ALL Equals (Carefully) List the names of departments where all employees are clerks SELECT dname FROM Depts d WHERE 'CLERK' = ALL (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) -- includes depts with no employees! WITH EmpDepts AS (SELECT DISTINCT d.* FROM (Depts d NATURAL JOIN Emps) SELECT dname FROM EmpDepts d WHERE 'CLERK' = ALL (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) -- excludes depts with no employees!

67 67 © Ellis Cohen 2001-2008 ALL Comparisons (Carefully) List the departments where every employee makes > 2000 SELECT dname FROM Depts d WHERE 2000 < ALL (SELECT e.sal FROM Emps e WHERE d.deptno = e.deptno) -- includes depts with no employees WITH EmpDepts AS (SELECT DISTINCT d.* FROM (Depts d NATURAL JOIN Emps) SELECT dname FROM EmpDepts d WHERE 2000 < ALL (SELECT e.sal FROM Emps e WHERE d.deptno = e.deptno) -- excludes depts with no employees Rewrite these using joins instead of subqueries

68 68 © Ellis Cohen 2001-2008 NOT with ANY & ALL What do these mean? SELECT dname FROM Depts d WHERE NOT( 'CLERK' = ALL (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) ) SELECT dname FROM Depts d WHERE NOT( 'CLERK' = ANY (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) )

69 69 © Ellis Cohen 2001-2008 NONE & NOT SOME List departments where some employee is not a clerk SELECT dname FROM Depts d WHERE NOT( 'CLERK' = ALL (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) ) List departments where none of the employees are clerks SELECT dname FROM Depts d WHERE NOT( 'CLERK' = ANY (SELECT e.job FROM Emps e WHERE d.deptno = e.deptno) )

70 70 © Ellis Cohen 2001-2008 Existence and Non-Existence The existence and non-existence of states of affairs in logical space is reality -- Ludwig Wittgenstein Tractatus Logico-philosophicus (translation by Robert Cavalier)

71 71 © Ellis Cohen 2001-2008 Checking for Existence List the names of employees who are project managers Find employees whose employee number is in the list of project managers SELECT ename FROM Emps WHERE empno IN (SELECT pmgr FROM Projs) Find employees where there is some project manager that matches the employee. SELECT ename FROM Emps e WHERE exists( SELECT * FROM Projs p WHERE p.pmgr = e.empno)

72 72 © Ellis Cohen 2001-2008 Existence Problem SELECT dname FROM Depts d WHERE exists( SELECT * FROM Emps e AND e.job = 'CLERK') What does this do?

73 73 © Ellis Cohen 2001-2008 Missing Correlation If any employee is a clerk, lists the names of all departments; else doesn’t list anything SELECT dname FROM Depts d WHERE exists( SELECT * FROM Emps e AND e.job = 'CLERK') List the names of depts that have clerks SELECT dname FROM Depts d WHERE exists( SELECT * FROM Emps e WHERE e.deptno = d.empno AND e.job = 'CLERK')

74 74 © Ellis Cohen 2001-2008 Counting Existence List the names of employees who are project managers SELECT ename FROM Emps e WHERE exists( SELECT * FROM Projs p WHERE p.pmgr = e.empno) SELECT ename FROM Emps e WHERE ( SELECT count(*) FROM Projs p WHERE p.pmgr = e.empno) > 0

75 75 © Ellis Cohen 2001-2008 Counting Non-Existence List the names of employees who are not project managers SELECT ename FROM Emps e WHERE NOT exists( SELECT * FROM Projs p WHERE p.pmgr = e.empno) SELECT ename FROM Emps e WHERE ( SELECT count(*) FROM Projs p WHERE p.pmgr = e.empno) = 0

76 76 © Ellis Cohen 2001-2008 Checking for Non-Existence List the names of employees who are NOT project managers Find employees whose employee number is NOT in the list of project managers SELECT ename FROM Emps WHERE empno NOT IN (SELECT pmgr FROM Projs) Find employees where there is no project manager equal to the employee's employee number. SELECT ename FROM Emps e WHERE NOT exists( SELECT * FROM Projs p WHERE p.pmgr = e.empno)

77 77 © Ellis Cohen 2001-2008 Non-Existence without Subqueries List the names of employees who are project managers SELECT DISTINCT ename FROM (Emps JOIN Projs ON empno = pmgr) List the names of employees who are not project managers SELECT DISTINCT ename FROM (Emps JOIN Projs ON empno != pmgr) -- Doesn't work!

78 78 © Ellis Cohen 2001-2008 Consider Anti-EquiJoin Matches 7499ALLEN... 7654MARTIN… 7844TURNER… empno ename … Emps 1...7844 2…7499 3… 4 pno … pmgr Projs SELECT DISTINCT ename FROM (Emps JOIN Projs ON empno != pmgr) Which tuples match?

79 79 © Ellis Cohen 2001-2008 Anti-EquiJoins Don't Work 7499ALLEN... 7654MARTIN… 7844TURNER… empno ename … Emps 1...7844 2…7499 3… 4 pno … pmgr Projs EVERY Emps tuple is matched!

80 80 © Ellis Cohen 2001-2008 Non-Existence without Subqueries SELECT DISTINCT ename FROM (Emps JOIN Projs ON empno <> pmgr) SELECT ename FROM Emps e WHERE exists ( SELECT * FROM Projs p WHERE e.empno != p.pmgr) SELECT ename FROM Emps e WHERE NOT exists ( SELECT * FROM Projs p WHERE e.empno = p.pmgr) Identical Very Different If only one employee is a project manager, lists all employees except that one If more than one employee is a project manager, lists ALL of them! Can you rewrite this without a subquery?

81 81 © Ellis Cohen 2001-2008 Non-Existence Using Outer Joins List the names of employees who are not project managers (Assuming names are unique) SELECT ename FROM (Emps LEFT JOIN Projs ON empno = pmgr) WHERE pno IS NULL

82 82 © Ellis Cohen 2001-2008 Non-Existence Using Except List the names of employees who are not project managers (Assuming names are unique) SELECT ename FROM Emps EXCEPT SELECT DISTINCT ename FROM Emps, Projs WHERE empno = pmgr Can you fix this so it works even if employees have duplicate names?

83 83 © Ellis Cohen 2001-2008 Non-Existence Using Except (with duplicate names) List the names of employees who are not project managers (if names might be duplicated) WITH NotProjMgr AS (SELECT empno, ename FROM Emps EXCEPT SELECT DISTINCT empno, ename FROM Emps, Projs WHERE empno = pmgr) SELECT ename FROM NotProjMgr

84 84 © Ellis Cohen 2001-2008 Existence Problems List the department names where some employees are clerks SELECT dname FROM Depts d WHERE exists( SELECT * FROM Emps e WHERE e.deptno = d.deptno AND e.job = 'CLERK') Using exists, write the SQL to List the department names where some employees are NOT clerks List the department names where NO employees are clerks

85 85 © Ellis Cohen 2001-2008 Existence Solutions List the department names where SOME employees are NOT clerks SELECT dname FROM Depts d WHERE exists( SELECT * FROM Emps e WHERE e.deptno = d.deptno AND e.job != 'CLERK') List the department names where NO employees are clerks SELECT dname FROM Depts d WHERE NOT exists( SELECT * FROM Emps e WHERE e.deptno = d.deptno AND e.job = 'CLERK')

86 86 © Ellis Cohen 2001-2008 Meaning of Anti-Non-Existence What does this code mean? SELECT dname FROM Depts d WHERE NOT exists( SELECT * FROM Emps e WHERE e.deptno = d.deptno AND e.job != 'CLERK')

87 87 © Ellis Cohen 2001-2008 All Clerks List the department names where ALL employees are clerks SELECT dname FROM Depts d WHERE NOT exists( SELECT * FROM Emps e WHERE e.deptno = d.deptno AND e.job != 'CLERK')


Download ppt "1 Theory, Practice & Methodology of Relational Database Design and Programming Copyright © Ellis Cohen 2002-2008 Subqueries These slides are licensed under."

Similar presentations


Ads by Google