Querying Multiple Tables with Joins
Data modeling is the strategic process of breaking application data into multiple tables and establishing relationships between them.
The Cost of One Large Table
Imagine tracking students and their course enrollments in one table. Each row might contain a student name, student ID, course name, course code, enrollment date, and grade. This looks simple at first, but the same student information must be repeated for every course the student takes. A student enrolled in five courses could appear in five rows.
Repeated information creates maintenance problems. If a student's email address changes, every row containing that student may need to be updated. If a course is not currently being taken, a single combined table may have no appropriate place to store that course without creating a misleading record. The problem is not merely that the table becomes large. Its structure mixes different kinds of things and repeats facts that should be stored once.
Planning a Data Model
Data modeling is the strategic process of breaking application data into multiple tables and establishing relationships between them.
Data modeling is a planning activity. Before writing SQL or creating a database, you decide which distinct types of things the application tracks, which information belongs with each type, and how those types connect. The result is a structure in which each focused table stores one kind of entity and relationships connect the tables.
A data model is the design blueprint for this structure. It shows the tables, their columns, their primary keys, their foreign keys, and their relationships. A primary key is the unique identifier for each row in a table. A foreign key is a column that references a primary key in another table. This blueprint helps reveal design problems before code is written or real data is stored.
Following Relationships Across Tables
Consider a library system. The Borrowers table stores each borrower once, with borrower_id, borrower_name, and borrower_email. The Books table stores each book once, with book_id, book_title, and book_author. The Checkouts table stores each transaction, with checkout_id, borrower_id, book_id, checkout_date, and due_date.
The borrower_id and book_id columns in Checkouts are foreign keys. They refer to specific rows in Borrowers and Books. If a checkout has borrower_id equal to 5, that value points to the borrower row whose borrower_id is 5. The same checkout's book_id points to the related book row. The tables remain separate, but the identifiers let the system reconstruct the complete borrowing event.
How a Join Reconstructs Information
A join combines information from related tables by following their matching identifiers. In the library model, a query can use a checkout's borrower_id to find the corresponding borrower and its book_id to find the corresponding book. The resulting view can bring together borrower details, book details, and checkout details without storing all of those facts repeatedly in one table.
The important sequence is: start with a record in one table, read its foreign key, locate the row whose primary key matches that value, and use the related row's columns as part of the combined result. A join therefore does not remove the separate tables. It uses their relationships to answer questions that span across them.
Library Model Worked Through
Separating borrowers, books, and checkouts
Design a structure for a library system that tracks borrowers, books, and borrowing transactions without repeating borrower or book details.
Identify the entities: The system tracks borrowers, books, and checkouts. These are distinct kinds of information, so they belong in separate focused tables.
Store each entity once: Borrowers stores borrower_id, borrower_name, and borrower_email. Books stores book_id, book_title, and book_author.
Record the relationship: Checkouts stores checkout_id, borrower_id, book_id, checkout_date, and due_date. Its borrower_id and book_id values refer to rows in the other two tables.
Use the relationship in a query: A join can follow borrower_id to obtain borrower details and book_id to obtain book details, then combine those details with the checkout information.
The library data is organized into three related tables. A borrower appears once, a book remains available as its own record even when it is not checked out, and a checkout connects the borrower and book through foreign keys.
The relationship table is not duplicate storage of the borrower and book. It records the transaction and stores the identifiers needed to connect that transaction to the relevant records.
Mistakes in Table Design
Keeping all application data in one sprawling table
Borrower and book information is repeated, so updates may need to be made in multiple rows.
Fix:
Separate the data into focused Borrowers, Books, and Checkouts tables.Treating a foreign key as unrelated data
The value is what connects the checkout to a specific row in Borrowers.
Fix:
Use the foreign key to locate the matching primary key in the related table.Designing tables before deciding what the application tracks
The resulting structure can contain unclear relationships or redundant data.
Fix:
Create a data model first as a planning blueprint.Assuming a separate table eliminates the need for relationships
The tables cannot be used together to reconstruct a complete borrowing event.
Fix:
Establish relationships through foreign keys that reference primary keys.
Practice the Connection
A library has Borrowers, Books, and Checkouts tables. A checkout record contains borrower_id and book_id. Explain, in order, how a query could obtain the borrower's name and the book's title for that checkout.
Hints
- Identify which table contains the checkout record.
- Follow borrower_id to the matching primary key in Borrowers.
- Follow book_id to the matching primary key in Books.
- Combine the matching borrower and book details with the checkout details.
- A strong answer says that the query starts with Checkouts, follows borrower_id to the matching Borrowers row, follows book_id to the matching Books row, and combines the selected columns. The tables remain separate; the join uses their relationships to produce a unified result.
What to Remember
- Data modeling organizes application data into multiple focused tables and establishes relationships between them.
- Separating data reduces redundancy and makes updates cleaner because each fact can be stored in an appropriate place.
- Foreign keys connect records by referencing primary keys in related tables.
- A join follows those relationships to combine matching information from multiple tables into one query result.
- A data model is the design blueprint showing the tables, columns, keys, and relationships before SQL is written.
Key Takeaways
- Multiple focused tables prevent repeated data and reduce maintenance problems.
- Data modeling is the planning process of organizing application data across related tables.
- Foreign keys connect records in one table to primary keys in another.
- Joins use those connections to reconstruct information from multiple tables.
- A data model documents the database structure before SQL and stored data exist.