Using the same table more than once in a query
To begin this module, the first reading shows how a table can be
joined to itself to answer queries that need data from more than one
row in a table. As well as illustrating a new technique, this reading
also provides a review of using the SELECT statement.
Subqueries

Ch8 pp 340-345
Subqueries is another method to retrieve information from multiple tables. Two readings are provided:
- The first reading, subqueries and Correlated Subqueries explains subqueries
- 
    
The second reading provides a brief summary of subqueries.
 As you read think about the processing order of the query execution.
If you wish, you can now complete questions 1-4 of Getting your hands dirty.
Combining queries

Ch8 pp 345-349
The reading Using Derived Tables, Combining Queries, Conditional Expressions and More Complicated SQL Queries cover:
- Constructing a temporary table to use in a query, and
- Combining the output of different queries together.
The following reading in Derived Tables provides a summary
of the UNION Statement.
Another viewpoint
Writing SQL queries is a knack and does take time and practice. To help you, an additional reading is included:
-  Elmasri provides an alternative explanation of the 
 SELECTstatement. As you work through, you might wish to try
 and write the queries before looking at the answers.
Alternatively, jump in the deep end and start working on the queries in the Getting Your Hands Dirty section.

 INVOICE
INVOICE
 INVOICE
INVOICETry the following queries on the INVOICE
database.

1. Find the items that have a price that is greater than the average
item price 

2. Find the most common item sold 
 
 
3. Find all the customers that have not had an invoice. (Note: This
is the opposite of an earlier query that finds all the customers that
have an invoice against them.) 

4. Find all the products that have never been sold. 
 

5. Find the items that have a price less than the average item
price. 

6. Find the product descriptions and item price of the most
expensive and least expensive items stocked  
 

 Check
Check
1. Find the items that have a price that is
greater than the average item price 


       SELECT ItemNo, ItemDesc,
ItemPrice
      FROM ITEM
      WHERE ItemPrice > (SELECT
AVG(ItemPrice)
                  
      FROM ITEM); 
The inner query is executed first and returns a single row:

The outer query is then executed, the value returned is placed in each row of the table created by the outer query and evaluated (as we know, SQL can only compare a single row at a time). The rows that match the criteria are returned.
2. Find the most common item sold 
 
 

      SELECT init.ItemNo, ItemDesc
      FROM InvoiceItem init, Item it
      WHERE init.ItemNo = it.ItemNo
      GROUP BY init.ItemNo, ItemDesc
      HAVING SUM(Quantity) >= ALL (SELECT
SUM(Quantity)
                             
FROM InvoiceItem
                             
GROUP BY ItemNo);
If we used the ANY operator in the above query, all of
the values from the inner query will be evaluated as true in the outer
query and displayed.  Try it and see.
The inner query returns:
 
 
This is then evaluated by the outer query.
3. Find all the customers that have not had an
invoice. (Note: This is the opposite of an earlier query that finds all
the customers that have an invoice against them.) 


This is the opposite of an earlier query that finds all the customers that have an invoice against them.
      SELECT CustABN AS ABN, CustName
AS Name
      FROM CUSTOMER
      WHERE CustABN NOT IN (SELECT c.CustABN
           
           
    FROM CUSTOMER c, INVOICE i
          
           
     WHERE c.CustABN = i.CustABN);
Here the logical NOT operator is used with the IN
operator. The inner query is the earlier query that found all customers
with an invoice against them. Using NOT IN will now
finds all the records that weren’t retuned by the inner query. 
4. Find all the products that have never been
sold. 
 


      SELECT i.ItemNo, ItemDesc
      FROM ITEM i
      WHERE NOT EXISTS (SELECT *
           
            FROM
INVOICEITEM ii
          
     
       WHERE i.ItemNo = ii.ItemNo); 
5. Find the items that have a price less than
the average item price. 


      SELECT ItemDesc, ItemPrice,
AvgPrice
      FROM (SELECT AVG(ItemPrice) AS AvgPrice
FROM ITEM), ITEM
      WHERE ItemPrice < AvgPrice; 
6. Find the product descriptions and item price
of the most expensive and least expensive items stocked  
 


In an earlier exercise we had found the most expensive and least expensive items stocked using:
      SELECT MAX(ItemPrice) AS
Dearest, MIN(ItemPrice) AS Cheapest 
      FROM ITEM;
To now include the product descriptions:
     (SELECT ItemDesc AS Item, ItemPrice
      FROM ITEM
      WHERE ItemPrice IN (SELECT MAX(ItemPrice)
           
             
FROM ITEM))
      UNION
     (SELECT ItemDesc AS Item, ItemPrice
      FROM ITEM
      WHERE ItemPrice IN (SELECT MIN(ItemPrice)
           
             
FROM ITEM)); 
 STUDENT
STUDENT
 STUDENT
STUDENT1. For students that took both HIT999 and HIT232, find their grades in both units?
2. Find all students who have the same coordinator as Donald Duck?
3. Find all students whose coordinator has no other students?
4. Find students who have coord no 23 or who did HIT999
5. Which Coordinators advise more than 10 students?
6. Find the number of students advised by coordinators who advise a student in 3rd year (completed more than 160 credit points) or advise a student taking HIT232
 Check
Check
1. For students that took both HIT999 and
HIT232, find their grades in both units? 
      SELECT g1.student_No,
g1.Course_No, g1.Grade, g2.Course_No, g2.Grade
      FROM Grade g1, Grade g2
      WHERE g1.student_No = g2.student_No
      AND g1.Course_No = 'HIT232'
      AND g2.Course_No = 'HIT999'; 
2. Find all students who have the same
coordinator as Donald Duck? 
      SELECT Name
      FROM Students
      WHERE Coordinator_No = (SELECT
Coordinator_No
           
           
      FROM Students
           
           
      WHERE Name = 'Donald Duck');
In this query the subquery only returned a single value and so the = operator could be used. Had the subquery returned more than one row or no rows and = still be used there would have been a runtime error.
In cases where a subquery could return no value, one value or many values, ANY or ALL should be used. This query could be rewritten as:
       SELECT Name
      FROM Students
      WHERE Coordinator_No = ANY (SELECT
Coordinator_No
           
           
          FROM Students
           
           
          WHERE Name = 'Donald
Duck'); 
3. Find all students whose coordinator has no
other students? 
      SELECT name
      FROM student s1
      WHERE NOT EXISTS ( SELECT *
           
            FROM
student s2
           
            WHERE s1.
name <> s2.name 
           
            AND
s1.coordinator_no = s2.coordinator_no); 
4. Find students who have coord no 23 or who
did HIT999 
      (SELECT Student_No
      FROM student;
      WHERE Coord_No = 23)
      UNION
      (SELECT Student_No
      FROM Grade
      WHERE Course_No='HIT999' ); 
5. Which Coordinators advise more than 10
students?
      SELECT Name
      FROM Coordinator 
      WHERE (SELECT Count(*)
            FROM
Student
            WHERE
Student.coord_no=Coordinator.coord_no) >10; 
6. Find the number of students advised by
coordinators who advise a student in 3rd year (completed more than 160
credit points) or advise a student taking HIT232 
      SELECT coord_no, Count(*)
      FROM Student
      GROUP BY coord_no
      HAVING max(total_units) > 160
      OR coord_no IN (SELECT coord_no
        
            FROM
grade, student
        
            WHERE
course_no = 'HIT232'
        
            AND
student.student_no = grade.student_no); 
 PRODUCT
PRODUCT
 PRODUCT
PRODUCTFor those of you who want or need some more practice, here are some additional queries based on a product database. If you are feeling confident you may wish to skip or skim through these.
First read the description of the product database.
Then try the following queries.
1. Find the manufacturers that sell printers but not PCs.
2. Find those hard disk sizes that occur in two or more PCs
3. Find those PC models that have both the same speed and RAM as at least one other PC. A PC should only be listed once.
4. Find those manufacturers of at least two different computers (Pcs or laptops) with speeds of at least 1000. Note the two computers could be a pc and laptop or 2 pcs or 2 laptops.
5. Find the PCs whose speed is slower than that of all Laptops?
6. Find the model number of the item (PC, laptop, or printer) with the highest price.
7. Find the maker(s) of the PC(s) with the fastest processor among all those PC's that have the smallest amount of RAM.


1. Find the manufacturers that sell printers
but not PCs. 
      (SELECT maker
      FROM Product p, printer pr
      WHERE p.model=pr.model)
      MINUS
      (SELECT maker
      FROM Product p, pc 
      WHERE p.model=pc.model); 
 2. Find those hard disk sizes that occur in
two or more PCs. 
      SELECT hd
      FROM pc
      GROUP by hd
      HAVING count(*) >=2; 
 3. Find those PC models that have both the
same speed and RAM as at least one other PC. A PC should only be listed
once. 
      SELECT DISTINCT pc1.model
      FROM pc pc1, pc pc2
      WHERE pc1.speed = pc2.speed
      AND pc1.ram = pc2.ram
      AND pc1.model <> pc2.model; 
4. Find those manufacturers of at least two
different computers (Pcs or laptops) with speeds of at least 1000. Note
the two computers could be a pc and laptop or 2 pcs or 2 laptops. 
      SELECT maker
      FROM (SELECT maker, p.model, pc.speed
            FROM
product p, pc
            WHERE
p.model=pc.model
            AND
pc.speed >= 1000
            UNION 
            SELECT
maker, p.model, l.speed
            FROM
product p, laptop l
            WHERE
p.model=l.model
            AND
l.speed >= 1000)
      GROUP BY maker
      HAVING count(*) >= 2; 
5. Find the PCs whose speed is slower than that
of all Laptops?
      SELECT *
      FROM pc
      WHERE speed <= ALL (select speed from
laptop);
OR
      SELECT *
      FROM pc
      WHERE speed < (SELECT min(speed) FROM
laptop); 
 6. Find the model number of the item (PC,
laptop, or printer) with the highest price. 
      SELECT model
      FROM 
            (SELECT
model, price FROM pc 
            UNION
            SELECT
model, price FROM laptop
            UNION
            SELECT
model, price FROM printer)
      WHERE price = (SELECT max(price)
           
      FROM
           
      (SELECT model, price FROM pc 
           
      UNION
           
      SELECT model, price FROM laptop
           
      UNION
           
      SELECT model, price FROM printer)); 
 7. Find the maker(s) of the PC(s) with the
fastest processor among all those PC's that have the smallest amount of
RAM. 
      SELECT p.maker
      FROM pc pc1, product p
      WHERE pc1.model = p.model
      AND ram = (SELECT min(ram) FROM pc)
      AND speed >= ALL( SELECT speed
           
            FROM pc
           
            WHERE
ram=pc1.ram);
      SELECT p.model, p.maker
      FROM pc, product p
      WHERE pc.model = p.model
      AND (ram, speed) IN (SELECT ram,
max(speed)
           
            FROM pc
           
           
      GROUP BY ram
           
           
      HAVING ram = (SELECT min(ram) FROM pc)
); 
 

 
 

