Phase 0 · Start here: databases, tables and SQL · Topic 0.2

Meet the practice database

Must know

Six small tables — departments, employees, customers, orders, products and order_items — that every example and exercise in this course uses.

Not started

Step 1 Understand it

Why you need it. Learning on a different made-up in every lesson means learning new data each time. With one small you get to know the by heart, so you can check any result by eye. That habit is what catches wrong , at work and in interviews.

New words in this topic (tap one to see what it means)

Watch it happen

AnimationThe practice database: six tables, two worlds
Read the animation as text
  1. Six small tables, from two worlds you already know. Every example and exercise in the course uses them, so it pays to know them by heart.
  2. The company: departments, and employees. Each employee has a dept_id pointing at a department, and a manager_id pointing at another employee (the loop).
  3. Awkward cases are planted on purpose, because real data always has them.
  4. The shop: customers place orders; order_items records which products are in each order, and how many.
  5. And the shop's planted cases. Each one is a lesson later on — NULLs, duplicates, missing matches, streaks.

Picture it

erDiagram
  DEPARTMENTS ||--o{ EMPLOYEES : "has"
  EMPLOYEES |o--o{ EMPLOYEES : "manages"
  CUSTOMERS ||--o{ ORDERS : "places"
  ORDERS ||--o{ ORDER_ITEMS : "contains"
  PRODUCTS ||--o{ ORDER_ITEMS : "is in"
  DEPARTMENTS {
    int dept_id PK
    text dept_name
    text location
  }
  EMPLOYEES {
    int emp_id PK
    text name
    int dept_id FK
    int manager_id FK
    int salary
    text hire_date
  }
  CUSTOMERS {
    int customer_id PK
    text name
    text email
    text city
    text signup_date
  }
  ORDERS {
    int order_id PK
    int customer_id FK
    text order_date
    int amount
    text status
  }
  PRODUCTS {
    int product_id PK
    text product_name
    text category
    int price
  }
  ORDER_ITEMS {
    int order_id PK, FK
    int product_id PK, FK
    int quantity
  }
Each box is a table; PK marks its and FK a . Read a line from left to right: one department has many employees, one customer places many orders, and order_items links orders to products, because one order can hold many products and one product can be in many orders. The loop on EMPLOYEES is manager_id pointing back into the same table.

The idea

There are two small worlds. The company: departments, and employees who belong to a department and report to a manager. The shop: customers place orders, each order contains products, and order_items records which products are in which order, and how many. A few awkward cases are planted on purpose, because real data always has them: an employee with no department, a customer with no orders, two people on the same salary, and an order with no amount.

How it works, step by step

  1. departments (4 rows): Engineering, Sales, Marketing and HR. HR has no employees yet.
  2. employees (8 rows): each has a dept_id that points at departments, and a manager_id that points at another employee. Asha runs the company, so her manager_id is . Gus has no department.
  3. customers (6 rows): Tom signed up twice with the same email. Omar has never ordered. Zoe didn't give a city.
  4. orders (10 rows), from January to March 2024: each has a customer_id. Order 106 was cancelled and has no amount.
  5. products (7 rows): nobody has bought the phone case.
  6. order_items (14 rows): one row per product in an order, with the quantity. An order's amount is the sum of quantity × price over its items.

Analogy

A training kitchen with a fixed pantry. Every recipe (query) uses the same ingredients, so you learn how each one behaves, and you notice straight away when a dish comes out wrong.

Where the analogy breaks

Real databases have hundreds of tables and millions of rows, so you can't check results by eye there. That is exactly why it pays to practise on data small enough that you can, and to build the habit of testing a query on a few known rows.

Worked examples

The departments table

sql
SELECT *
FROM departments
ORDER BY dept_id;

4 rows

dept_iddept_namelocation
1EngineeringLondon
2SalesManchester
3MarketingLondon
4HRLeeds

SELECT * means every . Use it to look at a table; in real queries, name the columns you need.

The employees table

sql
SELECT *
FROM employees
ORDER BY emp_id;

8 rows

emp_idnamedept_idmanager_idsalaryhire_date
1Asha1NULL950002019-03-01
2Ben11700002020-06-15
3Chen11700002021-01-10
4Dara21600002020-02-20
5Eli24450002022-07-01
6Fatima31520002021-09-12
7GusNULL4380002023-04-03
8Hana12800002022-11-30

Spot the planted cases: Asha's manager_id is NULL, Gus's dept_id is NULL, Ben and Chen both earn 70000, and Hana (80000) earns more than her manager Ben.

The orders table

sql
SELECT *
FROM orders
ORDER BY order_id;

10 rows

order_idcustomer_idorder_dateamountstatus
10112024-01-06120delivered
10212024-01-0780delivered
10312024-01-0845delivered
10422024-01-21200delivered
10512024-02-02150shipped
10632024-02-12NULLcancelled
10732024-02-2060delivered
10822024-03-0175delivered
10912024-03-1030delivered
11052024-03-1633pending

Customer 1 (Priya) placed five orders, three of them on consecutive days. Order 106 has no amount.

Must-know points

  • employees.dept_id points at departments.dept_id; employees.manager_id points at employees.emp_id — the same table.
  • orders.customer_id points at customers.customer_id.
  • order_items links orders and products: one row per product in an order.
  • Dates are stored as text in YYYY-MM-DD form, so sorting them as text also sorts them by date.
  • Amounts and prices are whole pounds, to keep the sums easy to check by hand.

Common mistakes

  • Assuming every employee has a department, or every customer has an order. NULLs and missing rows are where most wrong answers come from.
  • Assuming ids are in date order. Here they happen to be; in real data, always sort by the date column.
  • Writing a query before knowing the of each table — what one row means.

Step 2 Go further (free, optional)

Optional. The notes above are written to be enough on their own. These free resources give a second explanation and more practice.

Step 3 Practise

Try each one yourself first: out loud, or written and run in the practice box below, which saves every query you run. Then open the answer and compare.

  1. ExplainSay what it does and when to use it, in plain words, with no notes.

    Without looking, say what one row of order_items means, and how it connects orders to products.

    Show answer

    One row of order_items is one line on a receipt: "order X contains this many of product Y". For example, (102, 4, 2) means order 102 contains 2 of product 4, the desk lamp.

    order_id points to a row in orders (who bought it, when, the total). product_id points to a row in products (its name and price). So order_items is the link between the two: one order can hold many products, and one product can appear in many orders.

  2. Writefrom a blank page, then run it

    Write a query that shows every column of the customers table, sorted by customer_id.

    Show answer

    SELECT * means every column. customer_id puts them in id order, so you can see the two Tom rows (2 and 6) and Zoe's missing city.

    sql
    SELECT *
    FROM customers
    ORDER BY customer_id;

    6 rows

    customer_idnameemailcitysignup_date
    1Priyapriya@mail.comLondon2024-01-02
    2Tomtom@mail.comLeeds2024-01-20
    3Lenalena@mail.comLondon2024-01-30
    4Omaromar@mail.comBristol2024-02-14
    5Zoezoe@mail.comNULL2024-03-10
    6Tomtom@mail.comLeeds2024-03-20
  3. Predictsay it before you run it

    How many rows does SELECT * FROM order_items WHERE order_id = 102; return, and which products are they?

    Show answer

    2 rows: product 4 (the desk lamp, 2 of them) and product 5 (the backpack, 1).

    Check it against orders: 2 × £25 + 1 × £30 = £80, which is exactly order 102's amount. (ORDER BY product_id is added below so the order is fixed.)

    sql
    SELECT *
    FROM order_items
    WHERE order_id = 102
    ORDER BY product_id;

    2 rows

    order_idproduct_idquantity
    10242
    10251
  4. Edge casesSay what happens with NULLs, ties, duplicates or no rows at all, and fix it.

    List the planted cases from memory: who has no manager, who has no department, who has no orders, which product never sold, and which order has no amount.

    Show answer

    • No manager: Asha (manager_id is NULL; she is the boss).
    • No department: Gus (dept_id is NULL).
    • No orders: Omar. (The second Tom sign-up, customer 6, has none either; Tom's orders are all under id 2.)
    • Never sold: the phone case (product 7).
    • No amount: order 106, which was cancelled.

    The others worth knowing: HR has no employees, Ben and Chen earn the same, Hana earns more than her manager Ben, Tom signed up twice with the same email, Zoe has no city, and Priya ordered three days in a row.

Practice box: write and run your answers here

Ctrl/⌘ + Enter runs it. Select part of the query to run only that part.

Step 4 Interview-ready, then prove it

Your interview answer

About 20 to 40 seconds, said out loud.

Before writing any SQL in an interview, I look at the tables: what one row means in each, which columns are keys, and how the tables . Then I ask about the awkward cases — can this be NULL, can there be duplicates, can a customer have no orders — because those decide whether I need a , a or a . Two minutes of that saves a wrong answer.

Follow-up questions

Why look at the data before writing the query?

To learn the grain, the keys, and the awkward cases — NULLs, duplicates, missing matches — that change the answer.

What is the grain of a table?

What one row represents. One row of orders is one order; one row of order_items is one product within one order. Mixing grains is how totals get counted twice.

Tick each check when you can do it without notes

A topic is finished when you pass all four checks, not when you have read it. Be strict: if you had to look at the notes, it is not ticked yet.

  • Explain Say what it does and when to use it, in plain words, with no notes.
  • Write Write the query from a blank page, then run it to check.
  • Predict Read a query and say which rows it returns before you run it.
  • Edge cases Say what happens with NULLs, ties, duplicates or no rows at all, and fix it.

0 of 4 checks ticked.

Saved in this browser. Back it up or move it to another device.