Normalisation · Chuẩn hóa (Normalisation)
Why normalise?
Imagine storing every club booking in one table, with the coach repeated on every row: each booking of the Chess club would carry "Mr Ng" again and again.
That repetition causes problems. If Mr Ng leaves, you must update many rows; miss one and the data becomes inconsistent. Normalisation organises tables to remove this kind of redundancy.
Tại sao chuẩn hóa?
Hãy tưởng tượng lưu trữ mọi đặt chỗ câu lạc bộ trong một bảng, với huấn luyện viên lặp lại trên mọi hàng: mỗi lần đặt chỗ Câu lạc bộ Cờ vua sẽ mang "Anh Ng" xuất hiện đi lặp lại.
Sự lặp lại này gây ra vấn đề. Nếu Anh Ng rời đi, bạn phải cập nhật nhiều hàng; lỡ một hàng thì dữ liệu trở nên không nhất quán. Chuẩn hóa tổ chức các bảng để loại bỏ sự dư thừa này.
The normal forms
You normalise in steps:
- 1NF — every cell holds a single value (no lists or repeating groups), and the table has a primary key.
- 2NF — already 1NF, and no non-key column depends on only part of a composite key.
- 3NF — already 2NF, and no non-key column depends on another non-key column (no transitive dependency).
In the one-table version, coach depends on the club, not on the booking — a transitive dependency, so it is not in 3NF.
Các dạng chuẩn
Bạn chuẩn hóa theo từng bước:
- 1NF — mỗi ô chứa một giá trị đơn (không có danh sách hay nhóm lặp), và bảng có khóa chính.
- 2NF — đã là 1NF, và không có cột không khóa nào phụ thuộc vào chỉ một phần của khóa phức hợp.
- 3NF — đã là 2NF, và không có cột không khóa nào phụ thuộc vào một cột không khóa khác (không có phụ thuộc truyền).
Trong phiên bản một bảng, coach phụ thuộc vào club, không phải vào việc đặt chỗ — đây là sự phụ thuộc bắc cầu, vì vậy nó không nằm trong 3NF.
The normalised design
We split the data into two tables (the ones loaded here):
club(club_id, name, coach)— each club and its coach, stored once.booking(booking_id, student, club_id)— each booking, linked by the foreign keyclub_id.
Now a coach is stored once. A JOIN puts the information back together whenever you need it — write that join below.
Thiết kế đã chuẩn hóa
Chúng tôi tách dữ liệu thành hai bảng (các bảng được tải vào đây):
club(club_id, name, coach)— mỗi câu lạc bộ và huấn luyện viên của họ, được lưu trữ một lần duy nhất.booking(booking_id, student, club_id)— mỗi lần đặt chỗ, được liên kết qua khóa ngoạiclub_id.
Bây giờ một huấn luyện viên chỉ được lưu trữ một lần. Một JOIN sẽ tái cấu trúc thông tin bất cứ khi nào bạn cần — hãy viết câu nối đó ở dưới đây.
Common mistakes
- Split repeating groups into their own table instead of many similar columns.
- Each table should describe one kind of thing.
Những lỗi thường gặp
- Chia các nhóm lặp lại thành bảng riêng thay vì nhiều cột tương tự nhau.
- Mỗi bảng nên mô tả một loại đối tượng duy nhất.
Reassemble the data: list each booking's student next to their club's coach, by joining booking to club on club_id, ordered by booking.booking_id. · Gộp dữ liệu: liệt kê student của mỗi lần đặt chỗ bên cạnh coach của câu lạc bộ tương ứng, bằng cách nối booking với club dựa trên club_id, sắp xếp theo booking.booking_id.
Click Run to see the output here. · Nhấn Chạy để xem kết quả ở đây.
The split tables still answer questions together. Count how many bookings each club has: join booking to club, show club.name and COUNT(*) AS bookings, group by the club, and order by club.name. · Các bảng phân tách vẫn trả lời câu hỏi khi kết hợp. Đếm số lượng lần đặt chỗ của mỗi câu lạc bộ: nối booking với club, hiển thị club.name và COUNT(*) AS bookings, nhóm theo câu lạc bộ, và sắp xếp theo club.name.
Click Run to see the output here. · Nhấn Chạy để xem kết quả ở đây.