NULL values 
Care is needed when retrieving rows in tables that may contain NULL
values. As the reading shows, NULL has some unique
characteristics when compared to other values.
Multiple table queries
 
 Ch 7 pp 323-332
The following reading from your textbook Multiple Table Queries shows how to join tables together to retrieve information from multiple tables.

WHERE clause for each pair of tables
being joined. Thus, if two tables are to be combined, one condition
would be necessary, but if three tables (A, B and C) are to be
combined, then two conditions would be necessary because there are two
pairs of tables (A-B and B-C), and so forth. 
A summary of the different types of Joins is provided opposite .
Understanding the order in which the different parts of a SELECT
query are executed will help you write more complicated queries and
work out why other queries don't work as you expected.
Handling DATEs 
Oracle's treatment of DATEs does not follow the SQL
standard. This short reading explains how DATEs are
implemented and how to use them. If you wish, you can skip this section
until you come to the queries below that use DATEs.

Invoice database 1
Now try the following queries on the INVOICE database.
These activities relate to the PowerPoint Presentation “Multi-table queries” refer to “get your hands dirty”
1. Find the customer details for invoice 12
| CUSTABN | CUSTNAME | CUSTSUBURB | CUSTNAME | CUSTSTATE | CUSTPOSTCODE | 
|---|---|---|---|---|---|
| 17652258874 | Adams Tractors | 65 Earl St | Terara | NSW | 2540 | 
2. Find the names of all customers who brought an item with Tube in its description 
        
| CUSTNAME | 
|---|
| Victor Panels | 
| Astian Court Holdings | 
 3. Find the customers who live in NSW or Qld who brought Screens 
        
| CUSTNAME | 
|---|
| Victor Panels | 
| Mellow Yellow Lighting | 
| Australian Drums | 
| Australian Drums | 
 4. Find the number of Screens brought by customers in NSW and Qld 
        
| CUSTNAME | SUM(QUANTITY) | 
|---|---|
| Australian Drums | 10 | 
| Victor Panels | 5 | 
| Mellow Yellow Lighting | 4 | 
        
Check (invoice database 1)
The Answers to these will be available in Week Tasks multiple table queries.
          The specific day is mentioned in announcements.
 Invoice database 2
Invoice database 2
        Now try the following queries on the INVOICE database.
 1. For each customer that has an invoice, what is the customer's
          name and invoice number? 
        

2. Show which customers have received an invoice and sort by name.
          Remove any duplicates. 
        

3. Show the customer ABN and name and list all of the items as well
          as a quantity, description and price for invoice number 21. 
        

4. Find the number of invoices for each customer name. 
        

5. Find the customer name, invoice number and value of each invoice. 
        

6. Find the number of invoices for each customer whose name starts
          with A to E. Try writing this query two ways: once without the HAVING clause, once with the HAVING clause. 

7. Find all the customers who have more than one invoice. Could you
          write this query without the HAVING clause? 

8. For each customer, find out how much their invoices are worth. 

9. Find all the customers who have more than one invoice and have
          the letter t or T in their name. 

10. Find all customers who have invoices dated before August 2005. 

11. Find the customer name, invoice no and date (format MON 22
          AUGUST 2005) for invoices in August 2005. 

 Check (invoice database 2)
Check (invoice database 2)
        1. For each customer that has an invoice, what
          is the customer's name and invoice number? 


SELECT CUSTOMER.CustABN, CustName, InvoiceNo 
            FROM CUSTOMER, INVOICE 
            WHERE CUSTOMER.CustABN = INVOICE.CustABN; 
 Notice in the query we had to declare which table we
            wanted the CustABN to come from, and in the WHERE statement declare the fields in both tables.
This is because there is ambiguity, as CustABN exists
            in both tables. We must specify which table SQL Plus should pick the
            field from. This is only a problem when we have the same field names
            (notice we did not worry about CustName and InvoiceNo).
Remember that we can also uses aliases for our field names. We can
            also do the same for our tables. If the above query was a more involved
            one we would soon get sick of typing CUSTOMER.Something or INVOICE.Something.
We can make life easier with something like this:
SELECT CUSTOMER.CustABN AS ABN, CustName AS Name, InvoiceNo AS
            "Invoice Number" 
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN; 
This returns the same but with meaningful column headers. Note the
            use of double quotes as there is a space in the string.      
2. Show which customers have received an
          invoice and sort by name. Remove any duplicates. 
        


SELECT DISTINCT c.CustABN AS ABN, CustName AS Name 
            FROM CUSTOMER c, INVOICE i 
            WHERE c.CustABN = i.CustABN
            ORDER BY CustName; 
3. Show the customer ABN and name and list all
          of the items as well as a quantity, description and price for invoice
          number 21. 
        


SELECT c.CustABN, CustName, inv.InvoiceNo, Quantity,
            init.ItemNo, ItemDesc, ItemPrice 
            FROM CUSTOMER c, INVOICE inv, INVOICEITEM init, ITEM it 
            WHERE c.CustABN = inv.CustABN
            AND init.InvoiceNo = inv.InvoiceNo
            AND it.ItemNo = init.ItemNo
            AND inv.InvoiceNo = 21; 
4. Find the number of invoices for each
          customer name. 
        


SELECT CustABN, COUNT(InvoiceNo) 
            FROM INVOICE 
            GROUP BY CustABN;
As we want to display the name of the customers instead of the ABN,
            we need to join the CUSTOMER and the INVOICE tables. The linking field for the two tables is CustABN.
SELECT c.CustName, COUNT(i.InvoiceNo) 
            FROM CUSTOMER c, INVOICE i 
            WHERE c.CustABN = i.CustABN
            GROUP BY c.CustName;
We could also use aliases for CustName and COUNT(i.InvoiceNo)
5. Find the customer name, invoice number and
          value of each invoice. 
        


SELECT SUM(Quantity * ItemPrice) as InvTotal, CustName,
            inv.InvoiceNo 
            FROM InvoiceItem ii, Item i, Invoice inv, Customer c 
            WHERE ii.ItemNo = i.ItemNo
            AND inv.InvoiceNo = ii.InvoiceNo
            AND inv.CustABN = c.CustABN
            GROUP BY inv.InvoiceNo, CustName;
          
6. Find the number of invoices for each
          customer whose name starts with A to E. Try writing this query two
          ways: once without the HAVING clause, once
          with the HAVING clause. 


Without the HAVING clause:
SELECT c.CustName, COUNT(i.InvoiceNo)
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN
            AND c.CustName < 'F'
            GROUP BY c.CustName;
With the HAVING clause:
SELECT c.CustName, COUNT(i.InvoiceNo)
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN
            GROUP BY c.CustName
            HAVING c.CustName < 'F';
7. Find all the customers who have more than
          one invoice. Could you write this query without the HAVING clause? 


SELECT c.CustName, COUNT(i.InvoiceNo)
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN
            GROUP BY c.CustName
            HAVING COUNT(i.InvoiceNo) > 1;
Would this query work?
 SELECT c.CustName, COUNT(i.InvoiceNo)
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN
            AND COUNT(i.InvoiceNo) > 1
            GROUP BY c.CustName;

COUNT(i.InvoiceNo) > 1 will generate a syntax error.

WHERE works on
              individual rows - only rows that satisfy the condition(s) are included. HAVING works on groups - only groups that
              satisfy the condition(s) are included. Thus WHERE conditions cannot include grouping functions and HAVING cannot include conditions that operate at the row and not the group
              level. 
8. For each customer, find out how much their
          invoices are worth. 


SELECT c.CustName, SUM(Quantity*ItemPrice)
          FROM CUSTOMER c, INVOICE i, INVOICEITEM ii, ITEM it
          WHERE c.CustABN = i.CustABN
          AND i.InvoiceNo = ii.InvoiceNo
          AND ii.ItemNo = it.ItemNo
          GROUP BY c.CustName;9. Find all the customers who have more than
          one invoice and have the letter t or T in their name. 


SELECT c.CustName, COUNT(i.InvoiceNo)
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN
            AND (c.CustName LIKE '%t%' OR c.CustName LIKE '%T%')
            GROUP BY c.CustName;
Note the use of the ( )s. This ensures that the only rows included satisfy:
-  the join condition (c.CustABN = i.CustABN),and
-  have a 't' in their name (c.CustName LIKE '%t%' OR c.CustName LIKE '%T%')
Without the ( )s, namely:
 SELECT c.CustName, COUNT(i.InvoiceNo)
            FROM CUSTOMER c, INVOICE i
            WHERE c.CustABN = i.CustABN
            AND c.CustName LIKE '%t%' OR c.CustName LIKE '%T%'
            GROUP BY c.CustName;
The WHERE clause is interpreted as rows that satisfy
            either:
-  the first condition (c.CustABN = i.CustABN AND c.CustName LIKE '%t%'),or
-  the second condition(c.CustName LIKE '%T%').
This gives a rubbish answer.

AND has higher precedence than OR. So use ( )s
              in statements that have both AND and OR conditions.
10. Find all customers who have invoices dated
          before August 2005. 


SELECT DISTINCT CustName
          FROM CUSTOMER c, INVOICE i
          WHERE c.CustABN = i.CustABN
          AND TRUNC(InvDate) < DATE '2005-8-1';11. Find the customer name, invoice no and date
          (format MON 22 AUGUST 2005) for invoices in August 2005. 


SELECT CustName, InvoiceNo, To_CHAR(InvDate,
          'DY DD MONTH YYYY')
          FROM CUSTOMER c, INVOICE i
          WHERE c.CustABN = i.CustABN
          AND TRUNC(InvDate) >= DATE '2005-8-1' AND TRUNC(InvDate) <= DATE
          '2005-8-31';Invoice database 3
Now try the following queries on the INVOICE database.
These activities relate to the PowerPoint Presentation “Create Tables” refer to “get your hands dirty”
1. For customers living in Queensland, find the customer name, invoice number and invoice date
| CUSTNAME | INVOICENO | INVDATE | 
|---|---|---|
| Victor Panels | 20 | 28/AUG/05 | 
| Victor Panels | 5 | 13/APR/05 | 
| Lenton Holdings | 16 | 25/AUG/05 | 
| Australian Drums | 17 | 25/AUG/05 | 
| Astian Court Holdings | 10 | 10/JUN/05 | 
2. For customers living in Queensland, find the customer name, invoice number and invoice date for invoices with numbers greater than 18 or less than 11 
        
| CUSTNAME | INVOICENO | 
|---|---|
| Victor Panels | 5 | 
| Victor Panels | 20 | 
| Astian Court Holdings | 10 | 
 3. Find the number of invoices for each customer in Queensland 
        
| CUSTNAME | COUNT(*) | 
|---|---|
| Australian Drums | 1 | 
| Victor Panels | 2 | 
| Lenton Holdings | 1 | 
| Astian Court Holdings | 1 | 
 4. 	Can you find the answer to number 3, both using the having clause and not using it? 
        
| CUSTNAME | COUNT(*) | 
|---|---|
| Australian Drums | 1 | 
| Victor Panels | 2 | 
| Lenton Holdings | 1 | 
| Astian Court Holdings | 1 | 
Check (invoice database 3)
The Answers to these will be available in Week Tasks multiple table queries.
The specific day is mentioned in announcements.
 Student database - more
          SQL queries
Student database - more
          SQL queries 
        
        1. Which students have Fred Flintstone as their course coordinator?
2 Which students are doing the course Project?
3. For the coordinator with Employee_no AS1234, find his/her name and the average number of units the students he/she advises have completed.
4. For all the coordinators whose employee number start with AS find his/her name and the average number of units the students he/she advises have completed.
 Check (Student database)
Check (Student database)
        1. Which students have Fred Flintstone as their
          course coordinator? 
SELECT Student.Name 
            FROM Student, Coordinator 
            WHERE Student.Coord_No=Coordinator.Coord_No 
            AND Coordinator.Name = 'Fred Flinstone';
Note that for this query all the columns had to be qualified (e.g. Student.Name).
            The columns by themselves (e.g. Name or Coord_No)
            would have been ambiguous as they appeared in both tables. If the
            column name is unique in all tables involved in the query it need not
            be qualified e.g. the columns Employee_No or Total_Units are unique across both Student and Coordinator.
 2 Which students are doing the course Project? 
SELECT Student.Name 
            FROM Student, Course, Grade 
            WHERE Student.Student_No=Grade.Student_No 
            AND Course.Course_No = Grade.Course_No 
            AND Course.Name = 'Project';
 3. For the coordinator with Employee_no
          AS1234, find his/her name and the average number of units the students
          he/she advises have completed 
SELECT c.Name, AVG(Total_Units)
            FROM Student s, Coordinator c
            WHERE s.Coord_No = c. Coord_No
            AND Employee_No = 'AS1234'
            GROUP BY c.name;
Note that with this example the tables are joined together and the
            conditions calculated (the effect of the WHERE and AND clauses are computed) before the grouping and aggregations functions
            are applied. 
4. For all the coordinators whose employee
          number start with AS find his/her name and the average number of units
          the students he/she advises have completed.
SELECT c.Name, AVG(Total_Units)
            FROM Student s, Coordinator c
            WHERE s.Coord_No = c. Coord_No
            AND Employee_No LIKE 'AS%'
            GROUP BY c.name;
Or another alternate way to write the query would be:
SELECT c.Name, AVG(Total_Units)
            FROM Student s, Coordinator c
            WHERE s.Coord_No = c. Coord_No
            GROUP BY c.name, Employee_No
            HAVING Employee_No LIKE 'AS%';
Note to use the Employee_No column in the HAVING clause it needs to appear in the GROUP BY clause.
 






