lesson 17 Joins & sets · beginner
Databases, schemas, tables & keys
Understand tables, keys and how related data is organized.
the idea
A database holds tables; sqlite_schema lists them with their definitions. A primary key identifies each row of a table; a foreign key stores another table’s key, so orders.customer_id points at customers.customer_id. Joining along that relationship (FROM orders JOIN customers ON customers.customer_id = orders.customer_id) attaches customer attributes to each order.
Dataset: Retail
The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.
categories3 columns · 17 rows
| category_idnumber · unique id | category_nametext | departmenttext |
|---|---|---|
| 1 | Christmas & Seasonal | Seasonal |
| 2 | Candles & Lighting | Home |
| 3 | Kitchen & Dining | Home |
| 4 | Home Decor | Home |
| 5 | Storage & Organisation | Home |
| 6 | Bags & Accessories | Fashion |
- category_idnumber · unique id
- 1
- category_nametext
- Christmas & Seasonal
- departmenttext
- Seasonal
- category_idnumber · unique id
- 2
- category_nametext
- Candles & Lighting
- departmenttext
- Home
- category_idnumber · unique id
- 3
- category_nametext
- Kitchen & Dining
- departmenttext
- Home
- category_idnumber · unique id
- 4
- category_nametext
- Home Decor
- departmenttext
- Home
- category_idnumber · unique id
- 5
- category_nametext
- Storage & Organisation
- departmenttext
- Home
- category_idnumber · unique id
- 6
- category_nametext
- Bags & Accessories
- departmenttext
- Fashion
first 6 of 17 rows · your queries use all of them
customers4 columns · 848 rows
| customer_idnumber · unique id | countrytext | regiontext | first_order_atdate & time |
|---|---|---|---|
| 12347 | Iceland | Europe | 2010-10-31 14:20:00 |
| 12353 | Bahrain | Rest of World | 2010-10-27 12:44:00 |
| 12359 | Cyprus | Europe | 2009-12-05 13:32:00 |
| 12373 | Austria | Europe | 2010-02-04 12:08:00 |
| 12374 | Austria | Europe | 2010-04-30 14:01:00 |
| 12384 | Switzerland | Europe | 2011-08-10 11:23:00 |
- customer_idnumber · unique id
- 12347
- countrytext
- Iceland
- regiontext
- Europe
- first_order_atdate & time
- 2010-10-31 14:20:00
- customer_idnumber · unique id
- 12353
- countrytext
- Bahrain
- regiontext
- Rest of World
- first_order_atdate & time
- 2010-10-27 12:44:00
- customer_idnumber · unique id
- 12359
- countrytext
- Cyprus
- regiontext
- Europe
- first_order_atdate & time
- 2009-12-05 13:32:00
- customer_idnumber · unique id
- 12373
- countrytext
- Austria
- regiontext
- Europe
- first_order_atdate & time
- 2010-02-04 12:08:00
- customer_idnumber · unique id
- 12374
- countrytext
- Austria
- regiontext
- Europe
- first_order_atdate & time
- 2010-04-30 14:01:00
- customer_idnumber · unique id
- 12384
- countrytext
- Switzerland
- regiontext
- Europe
- first_order_atdate & time
- 2011-08-10 11:23:00
first 6 of 848 rows · your queries use all of them
orders6 columns · 6,722 rows
| order_idnumber · unique id | invoice_notext | customer_idnumber · links to customers | ordered_atdate & time | countrytext | order_typetext |
|---|---|---|---|---|---|
| 1 | 489438 | 18102 | 2009-12-01 09:24:00 | United Kingdom | sale |
| 2 | 489517 | 16329 | 2009-12-01 11:34:00 | United Kingdom | sale |
| 3 | C489528 | 16714 | 2009-12-01 11:50:00 | United Kingdom | cancellation |
| 4 | 489529 | 17984 | 2009-12-01 11:51:00 | United Kingdom | sale |
| 5 | 489532 | 13394 | 2009-12-01 11:58:00 | United Kingdom | sale |
| 6 | 489540 | 12913 | 2009-12-01 12:18:00 | United Kingdom | sale |
- order_idnumber · unique id
- 1
- invoice_notext
- 489438
- customer_idnumber · links to customers
- 18102
- ordered_atdate & time
- 2009-12-01 09:24:00
- countrytext
- United Kingdom
- order_typetext
- sale
- order_idnumber · unique id
- 2
- invoice_notext
- 489517
- customer_idnumber · links to customers
- 16329
- ordered_atdate & time
- 2009-12-01 11:34:00
- countrytext
- United Kingdom
- order_typetext
- sale
- order_idnumber · unique id
- 3
- invoice_notext
- C489528
- customer_idnumber · links to customers
- 16714
- ordered_atdate & time
- 2009-12-01 11:50:00
- countrytext
- United Kingdom
- order_typetext
- cancellation
- order_idnumber · unique id
- 4
- invoice_notext
- 489529
- customer_idnumber · links to customers
- 17984
- ordered_atdate & time
- 2009-12-01 11:51:00
- countrytext
- United Kingdom
- order_typetext
- sale
- order_idnumber · unique id
- 5
- invoice_notext
- 489532
- customer_idnumber · links to customers
- 13394
- ordered_atdate & time
- 2009-12-01 11:58:00
- countrytext
- United Kingdom
- order_typetext
- sale
- order_idnumber · unique id
- 6
- invoice_notext
- 489540
- customer_idnumber · links to customers
- 12913
- ordered_atdate & time
- 2009-12-01 12:18:00
- countrytext
- United Kingdom
- order_typetext
- sale
first 6 of 6,722 rows · your queries use all of them
worked example
Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.
List tables in the database. Run this. sqlite_schema names every table and view the database defines.
step-1.sqlSELECT name, type FROM sqlite_schema WHERE type IN ('table', 'view') ORDER BY name;
Read a table’s CREATE statement. Run this. The sql column shows columns, primary keys, and foreign keys for orders.the pattern
example.sqlSELECT name, sql FROM sqlite_schema WHERE type = 'table' AND name = 'orders';
Attach customer columns with LEFT JOIN. Run this. Each order’s customer_id looks up customers; anonymous orders stay with NULL customer fields.
step-3.sqlSELECT o.order_id, o.customer_id, c.country, c.region FROM orders o LEFT JOIN customers c ON c.customer_id = o.customer_id ORDER BY o.order_id LIMIT 10;
common mistake
A NULL foreign key (an anonymous order) matches no customer, so an inner join drops it.