[Courses] [Postgresql] Week 5: Even More SQL

Michelle Murrain michelle at murrain.net
Mon Jan 7 22:43:49 UTC 2008


Hi all,

Here are this week's assignments. Have fun!

Next week is much more PG-specific, we'll talk about PG's permission 
systems and system catalogs.

And please come for the chat tomorrow: 1:00 EST / 18:00 UTC on #courses 
at irc.linuxchix.org

Peace,
Michelle

=== Week 5: Even More SQL ===

Last week, we did a quick overview of creating databases and tables, 
inserting data, and selecting data. SQL is a very rich language, and 
there is a lot to learn about it - it's impossible to cover very much in 
this course.

Quick review:

CREATE DATABASE database_name; - this will create a database called 
"database_name" using the standard template (template1)

CREATE TABLE table_name (field_name1 type, field_name2 type, field_name3 
type); - this will create a table.

INSERT INTO table_name (field_name1, field_name2, field_name3) VALUES 
('foo','bar','235'); - this inserts a row into the table

SELECT * FROM table_name; - this will select all fields and all rows in 
a table.

(A note about SELECT * vs SELECT ALL - there have been changes in the 
SQL syntax of postgresql, and I was incorrect, as many of you already 
found, about the select statement. The proper form to select all fields 
from a table is to use SELECT * not SELECT ALL)

SELECT * FROM table_name where field_name1='foo'; - this will select all 
fields from the table where the value of field_name is equal to 'foo'.

We'll talk more about selects some when we talk about operators later in 
the course.

**Even More SQL**

The thing I will focus on today is relationships, and how to create, and 
select from related tables.

Using relationships make databases very powerful. I mentioned 
normalization last time - that is a way to make sure that the data 
stored in relational databases is easy to retrieve and analyze.

Here's an example of some tables that are related, and how to get data 
out of them.

Lets take an example database for a bookstore. 4 tables: books, 
customers, orders, order details.

Books have the following data:

^ book_id  ^ title ^ author ^ cost |
| 1 | The Golden Compass | Phillip Pullman | 10 |
| 2 | The Bible          |   god           | 15 |
| 3 | Linux Cookbook     | Carla Schroeder | 35 |
| 4 | GIMP               | Akkana Peck     | 35 |
| 5 | The Hobbit         | J.R.R. Tolkien  | 15 |

Customers:

^ customer_id  ^ customer_last  ^ customer_first  ^ city |
|1| Murrain   | Michelle | Shelburne Falls |
|2| Schmo     | Joe      | New York        |
|3| Sunflower | Penelope | San Francisco   |

Orders:

^ order_id  ^ customer_id ^ date |
|   1        |   2        |2008-01-02|
|   2        |   1        |2008-01-02|
|   3        |   3        |2008-01-03|
|   4        |   1        |2008-01-04|

Order details:

^ order_detail_id ^ order_id ^ book_id |
|     1            |    1     |   4    |
|     2            |    1     |   5    |
|     3            |    1     |   2    |
|     4            |    2     |   3    |
|     5            |    2     |   4    |
|     6            |    3     |   1    |
|     7            |    3     |   2    |

order_id in the order_details table is called a "foreign key". As is 
customer_id in the orders table.

So, now the question. How do you reconstruct an order?

SELECT * from customers, books, orders, order details where 
customers.customer_id=orders.customer_id and 
order_details.order_id=orders.order_id and 
books.book_id=order_details.book_id and order_id='1';

You likely wouldn't want to do this - there will be fields in all of 
those tables you wouldn't want to display. In addition, this would spit 
out the customer name and city for each book they ordered. More likely, 
in an application, you'd first reconstruct the basics of the order:

SELECT customer_first,customer_last,city,date from orders,customers 
where orders.customer_id=customers.customer_id and order_id='1';

Then, get the list of books;

SELECT name,author from books, order_details where 
books.book_id=order_details.book_id and order_id='1';

When you use the construction: orders.customer_id=customers.customer_id 
you are asking the database system to match records, and only return 
those that match. This is the same as what is called an "inner join".

You could find all the orders by using:

SELECT customer_first,customer_last,city,date FROM orders INNER JOIN 
customers ON orders.customer_id = customers.order_id;

You could also find all customers, even if they didn't have an order by 
using what is called a "Left join" (or "left outer join":

SELECT customer_first,customer_last,city,date LEFT JOIN orders ON 
orders.customer_id = customers.order_id;

A "right join" or "right outer join" would do the reverse - list orders, 
even if there were no customers.


**Assignments**

You wanted to sponsor a screening of the film "The Golden Compass" at a 
theatre in NY. What SQL statement would you use to find all of the 
people who had bought that book who lived in NY?

Create your own set of related tables. Try inner and outer joins. What 
have you learned.

Extra credit:

What's a cross join, and when would that be useful?
What's a full outer join?

-- 
Michelle Murrain
Coordinator, Nonprofit Open Source Initiative
http://nosi.net

Skype: pearlbear
AIM: pearlbear0


More information about the Courses mailing list