Appearance
🏆 Tiêu chuẩn Buổi 5: SQL — SELECT, JOIN & Aggregation
Các tiêu chuẩn và framework quốc tế cần nắm cho SQL Querying, JOIN, GROUP BY và Data Modeling
Tổng quan
Buổi 5 đưa bạn từ spreadsheet sang database — từ Excel sang SQL, từ VLOOKUP sang JOIN, từ Pivot Table sang GROUP BY. Đây là bước chuyển then chốt trong hành trình Data Analyst: từ xử lý file cục bộ sang truy vấn hệ thống dữ liệu chuyên nghiệp quy mô doanh nghiệp.
SQL không phải "viết kiểu gì cũng được". Giống như ngôn ngữ tự nhiên có ngữ pháp, SQL có chuẩn quốc tế (ANSI/ISO SQL) đảm bảo query chạy được trên mọi hệ thống. Giống như code có coding convention, SQL có Style Guide giúp query dễ đọc, dễ bảo trì. Và giống như kiến trúc có bản vẽ kỹ thuật, database có Data Modeling Standards giúp thiết kế bảng, quan hệ, và schema đúng chuẩn.
Các tiêu chuẩn trong buổi này cung cấp:
- Chuẩn ngôn ngữ SQL quốc tế: ANSI SQL đảm bảo syntax nhất quán, portable giữa các hệ thống (PostgreSQL, MySQL, SQL Server, BigQuery...)
- Convention viết query: SQL Style Guide giúp query dễ đọc, dễ review, dễ debug — đặc biệt quan trọng khi làm việc nhóm
- Nguyên tắc thiết kế database: DAMA DMBOK Data Modeling cung cấp framework cho relational database design, normalization, và naming convention
- Tư duy có hệ thống: Hiểu tiêu chuẩn giúp bạn viết SQL "có nguyên tắc", không phải "viết bừa rồi sửa"
Theo khảo sát Stack Overflow Developer Survey 2025, SQL là ngôn ngữ được sử dụng rộng rãi nhất (51% developers), và 92% doanh nghiệp Fortune 500 sử dụng relational database tuân theo chuẩn ANSI SQL. Viết SQL đúng chuẩn không chỉ giúp query chạy đúng, mà còn thể hiện sự chuyên nghiệp của một Data Analyst.
📋 Danh sách tiêu chuẩn liên quan
| # | Tiêu chuẩn | Tổ chức / Tác giả | Áp dụng cho Buổi 5 |
|---|---|---|---|
| 1 | ANSI/ISO SQL Standard | ANSI / ISO (ISO/IEC 9075) | Chuẩn SQL quốc tế — syntax SELECT, JOIN, GROUP BY, aggregate functions |
| 2 | SQL Style Guide | Simon Holywell / GitLab / Mozilla | Convention đặt tên, format query, indentation — giúp SQL dễ đọc & bảo trì |
| 3 | DAMA DMBOK — Data Modeling | DAMA International | Thiết kế relational database: normalization, naming convention, ERD standards |
| 4 | Codd's 12 Rules | Edgar F. Codd (1970, 1985) | Nguyên tắc nền tảng của relational database — hiểu bản chất hệ thống bạn đang query |
| 5 | ISO/IEC 11179 — Metadata Registry | ISO / IEC | Chuẩn đặt tên data element — naming convention cho cột, bảng trong database |
1️⃣ ANSI/ISO SQL Standard (ISO/IEC 9075)
Giới thiệu
ANSI SQL (American National Standards Institute SQL) là chuẩn quốc tế cho ngôn ngữ SQL, được quản lý bởi ANSI (Mỹ) và ISO (quốc tế) dưới mã ISO/IEC 9075. Phiên bản đầu tiên ra đời năm 1986, và đã trải qua nhiều lần cập nhật: SQL-89, SQL-92, SQL:1999, SQL:2003, SQL:2008, SQL:2011, SQL:2016, SQL:2023 — mỗi phiên bản bổ sung tính năng mới nhưng vẫn giữ backward compatibility.
Tại sao cần chuẩn? Vì thế giới có hàng chục hệ quản trị database khác nhau — PostgreSQL, MySQL, SQL Server, Oracle, SQLite, BigQuery, Snowflake... Nếu mỗi hệ thống dùng syntax riêng hoàn toàn, Data Analyst phải học lại từ đầu mỗi khi đổi công ty. ANSI SQL đóng vai trò "tiếng Anh của database" — dù bạn dùng hệ thống nào, 80–90% cú pháp đều giống nhau nhờ tuân theo chuẩn ANSI.
Trong thực tế, mỗi vendor (PostgreSQL, MySQL...) có thêm các extension riêng (dialect), nhưng core syntax — SELECT, FROM, WHERE, JOIN, GROUP BY, ORDER BY, HAVING — đều theo chuẩn ANSI SQL. Nắm vững ANSI SQL nghĩa là bạn viết query portable, chạy được trên hầu hết hệ thống mà không cần sửa.
Nội dung chính
Các thành phần ANSI SQL liên quan Buổi 5
| Thành phần | Phân loại SQL | Mô tả | Câu lệnh |
|---|---|---|---|
| DQL | Data Query Language | Truy vấn, đọc dữ liệu — trọng tâm Buổi 5 | SELECT |
| DML | Data Manipulation Language | Thêm, sửa, xóa dữ liệu | INSERT, UPDATE, DELETE |
| DDL | Data Definition Language | Tạo, sửa cấu trúc bảng | CREATE TABLE, ALTER TABLE, DROP TABLE |
| DCL | Data Control Language | Phân quyền truy cập | GRANT, REVOKE |
| TCL | Transaction Control Language | Quản lý giao dịch | COMMIT, ROLLBACK |
💡 Data Analyst chủ yếu dùng DQL (SELECT) — đọc và tổng hợp dữ liệu. Khác với Database Developer hay DBA, DA hiếm khi INSERT/UPDATE/DELETE trực tiếp trên production database.
Thứ tự viết vs. Thứ tự thực thi SQL (ANSI Standard)
Hiểu thứ tự thực thi giúp bạn debug query hiệu quả và viết query tối ưu:
| Thứ tự viết | Clause | Thứ tự thực thi | Mô tả |
|---|---|---|---|
| 1 | SELECT | 5 | Chọn cột cần hiển thị |
| 2 | FROM | 1 | Xác định bảng nguồn |
| 3 | JOIN | 2 | Kết nối bảng |
| 4 | WHERE | 3 | Lọc dòng trước khi gom nhóm |
| 5 | GROUP BY | 4 | Gom nhóm dữ liệu |
| 6 | HAVING | 6 | Lọc nhóm sau khi gom |
| 7 | ORDER BY | 7 | Sắp xếp kết quả |
| 8 | LIMIT / FETCH | 8 | Giới hạn số dòng trả về |
sql
-- Thứ tự viết (syntax order):
SELECT category, SUM(total_amount) AS revenue -- 5: chọn cột
FROM orders -- 1: từ bảng nào
JOIN products ON orders.product_id = products.id -- 2: kết nối bảng
WHERE order_date >= '2026-01-01' -- 3: lọc dòng
GROUP BY category -- 4: gom nhóm
HAVING SUM(total_amount) > 1000000 -- 6: lọc nhóm
ORDER BY revenue DESC -- 7: sắp xếp
LIMIT 10; -- 8: giới hạn
-- Execution order: FROM → JOIN → WHERE → GROUP BY → SELECT → HAVING → ORDER BY → LIMITANSI JOIN Types — Chuẩn kết nối bảng
| Loại JOIN | ANSI Standard | Mô tả | Kết quả |
|---|---|---|---|
INNER JOIN | ✅ SQL-92 | Chỉ dòng khớp cả 2 bảng | Bỏ dòng không khớp |
LEFT [OUTER] JOIN | ✅ SQL-92 | Tất cả dòng bảng trái + dòng khớp bảng phải | NULL nếu bảng phải không có |
RIGHT [OUTER] JOIN | ✅ SQL-92 | Tất cả dòng bảng phải + dòng khớp bảng trái | NULL nếu bảng trái không có |
FULL [OUTER] JOIN | ✅ SQL-92 | Tất cả dòng cả 2 bảng | NULL ở bên nào không khớp |
CROSS JOIN | ✅ SQL-92 | Tích Descartes — mỗi dòng A × mỗi dòng B | Ít dùng, cẩn thận data explosion |
NATURAL JOIN | ✅ SQL-92 | Tự động JOIN theo cột cùng tên | Không khuyến nghị — implicit, dễ sai |
⚠️ Best practice ANSI: Luôn dùng explicit JOIN syntax (
INNER JOIN,LEFT JOIN) thay vì implicit join (liệt kê bảng trong FROM + WHERE). Explicit JOIN rõ ràng hơn, dễ đọc hơn, và là chuẩn SQL-92.
ANSI Aggregate Functions
| Function | Mô tả | Ví dụ | NULL handling |
|---|---|---|---|
COUNT(*) | Đếm tất cả dòng | COUNT(*) = 100 | Đếm cả dòng có NULL |
COUNT(column) | Đếm dòng không NULL | COUNT(email) = 95 | Bỏ qua NULL |
COUNT(DISTINCT col) | Đếm giá trị duy nhất | COUNT(DISTINCT city) = 12 | Bỏ qua NULL |
SUM(column) | Tổng | SUM(total_amount) | Bỏ qua NULL |
AVG(column) | Trung bình | AVG(unit_price) | Bỏ qua NULL — cẩn thận! |
MIN(column) | Giá trị nhỏ nhất | MIN(order_date) | Bỏ qua NULL |
MAX(column) | Giá trị lớn nhất | MAX(total_amount) | Bỏ qua NULL |
⚠️ ANSI NULL trap:
AVG()bỏ qua NULL, không tính NULL = 0. Ví dụ:AVG(100, 200, NULL)= 150 (không phải 100). Nếu muốn NULL = 0, dùngAVG(COALESCE(column, 0)).
Áp dụng cho Data Analyst
| Tình huống DA | ANSI SQL áp dụng thế nào |
|---|---|
| Query data từ database | SELECT + FROM + WHERE — cú pháp ANSI đảm bảo chạy trên mọi hệ thống |
| Kết nối bảng customers + orders | ANSI JOIN syntax — explicit, rõ ràng, không dùng implicit join |
| Tổng hợp doanh thu theo nhóm | GROUP BY + SUM/COUNT/AVG — aggregate functions chuẩn ANSI |
| Lọc nhóm sau aggregation | HAVING — phân biệt rõ với WHERE (trước vs sau GROUP BY) |
| Chuyển đổi giữa các database | ANSI SQL portable — query viết trên PostgreSQL có thể chạy trên BigQuery với ít thay đổi |
| Xử lý NULL | Hiểu ANSI NULL handling — tránh sai kết quả khi COUNT, AVG |
| Phỏng vấn xin việc DA | Câu hỏi SQL interview luôn dựa trên ANSI SQL standard |
Tip thực tế: Khi viết SQL, luôn ưu tiên ANSI-compliant syntax. Tránh dùng syntax đặc thù của 1 vendor (ví dụ: LIMIT là ANSI SQL:2008 nhưng SQL Server dùng TOP, Oracle dùng FETCH FIRST). Nếu cần dùng dialect-specific, hãy ghi comment giải thích.
Ví dụ thực tế
Tình huống: Data Analyst cần phân tích doanh thu quý, top sản phẩm và đơn hàng theo khu vực từ database e-commerce.
❌ Viết SQL KHÔNG theo chuẩn ANSI (implicit join, non-standard):
sql
-- Implicit join (SQL cũ trước SQL-92) — KHÔNG khuyến nghị
SELECT o.order_id, c.customer_name, p.product_name, oi.quantity * oi.unit_price
FROM orders o, customers c, order_items oi, products p
WHERE o.customer_id = c.customer_id
AND o.order_id = oi.order_id
AND oi.product_id = p.product_id
AND o.order_date >= '2026-01-01'✅ Viết SQL THEO chuẩn ANSI (explicit JOIN, rõ ràng):
sql
-- ANSI SQL-92 explicit JOIN — khuyến nghị
SELECT
o.order_id,
c.customer_name,
p.product_name,
oi.quantity * oi.unit_price AS line_total
FROM orders AS o
INNER JOIN customers AS c
ON o.customer_id = c.customer_id
INNER JOIN order_items AS oi
ON o.order_id = oi.order_id
INNER JOIN products AS p
ON oi.product_id = p.product_id
WHERE o.order_date >= '2026-01-01'
ORDER BY o.order_id;Sự khác biệt:
- Explicit JOIN: mỗi bảng kết nối rõ ràng, điều kiện ON tách biệt khỏi WHERE
- Dễ thêm/bớt bảng mà không ảnh hưởng logic lọc
- Dễ chuyển INNER JOIN → LEFT JOIN khi cần giữ lại dòng không khớp
2️⃣ SQL Style Guide — Convention viết query
Giới thiệu
SQL Style Guide là tập hợp các convention (quy ước) về cách format, đặt tên, và tổ chức câu lệnh SQL. Dù SQL không yêu cầu format cụ thể để chạy (bạn có thể viết toàn bộ query trên 1 dòng), nhưng query dễ đọc = query ít bug hơn. Trong môi trường doanh nghiệp, query của bạn sẽ được đồng nghiệp đọc, review, và maintain — format chuẩn giúp giao tiếp hiệu quả hơn.
Một số SQL Style Guide phổ biến:
| Style Guide | Tổ chức / Tác giả | Đặc điểm |
|---|---|---|
| SQL Style Guide | Simon Holywell (sqlstyle.guide) | Phổ biến nhất, dựa trên Joe Celko's SQL Programming Style |
| GitLab SQL Style Guide | GitLab Inc. | Practical, dùng cho data team nội bộ GitLab |
| Mozilla SQL Style Guide | Mozilla Foundation | Concise, tập trung BigQuery/analytics |
| dbt SQL Style Guide | dbt Labs | Cho dbt projects, analytics engineering |
| Kickstarter SQL Style Guide | Kickstarter | Ngắn gọn, thực tế |
Tất cả đều có chung nguyên tắc cốt lõi: consistency, readability, maintainability. Bài này tổng hợp best practices từ nhiều style guide phổ biến nhất.
Nội dung chính
Quy tắc đặt tên (Naming Convention)
| Đối tượng | Convention | ✅ Good | ❌ Bad |
|---|---|---|---|
| Table name | snake_case, số nhiều | customers, order_items | Customer, OrderItem, tbl_order |
| Column name | snake_case, descriptive | customer_name, order_date | CustNm, od, field1 |
| Primary key | id hoặc table_id | customer_id, order_id | ID, custID, pk_customer |
| Foreign key | referenced_table_id | orders.customer_id | orders.cust, orders.fk1 |
| Boolean column | Prefix is_, has_, can_ | is_active, has_discount | active, discount_flag |
| Date column | Suffix _date, _at | created_at, order_date | date1, dt |
| Amount column | Suffix _amount, _total | total_amount, discount_amount | amt, total |
| Alias | Có ý nghĩa, snake_case | AS total_revenue | AS x, AS tr |
Format & Indentation
✅ Good SQL Formatting:
sql
SELECT
c.customer_id,
c.customer_name,
c.city,
COUNT(o.order_id) AS total_orders,
SUM(o.total_amount) AS total_revenue,
AVG(o.total_amount) AS avg_order_value
FROM customers AS c
LEFT JOIN orders AS o
ON c.customer_id = o.customer_id
WHERE c.segment = 'Premium'
AND o.order_date >= '2026-01-01'
GROUP BY
c.customer_id,
c.customer_name,
c.city
HAVING SUM(o.total_amount) > 5000000
ORDER BY total_revenue DESC
LIMIT 20;❌ Bad SQL Formatting:
sql
select c.customer_id,c.customer_name,c.city,count(o.order_id) as total_orders,sum(o.total_amount) as total_revenue,avg(o.total_amount) as avg_order_value from customers c left join orders o on c.customer_id=o.customer_id where c.segment='Premium' and o.order_date>='2026-01-01' group by c.customer_id,c.customer_name,c.city having sum(o.total_amount)>5000000 order by total_revenue desc limit 20;💡 Cả hai query cho ra cùng kết quả, nhưng query nào dễ đọc hơn? Dễ phát hiện lỗi hơn? Dễ sửa đổi hơn? Câu trả lời rõ ràng.
10 Quy tắc format SQL cốt lõi
| # | Quy tắc | Mô tả | Ví dụ |
|---|---|---|---|
| 1 | Keywords UPPERCASE | Viết hoa tất cả SQL keywords | SELECT, FROM, WHERE, JOIN, GROUP BY |
| 2 | Mỗi clause 1 dòng | Mỗi clause chính bắt đầu dòng mới | SELECT dòng 1, FROM dòng 2, WHERE dòng 3... |
| 3 | Indent cột & điều kiện | Cột trong SELECT, điều kiện trong WHERE indent 4 spaces | 4 spaces hoặc 1 tab |
| 4 | Mỗi cột 1 dòng trong SELECT | Dấu phẩy đầu dòng hoặc cuối dòng (chọn 1 và nhất quán) | Trailing comma phổ biến hơn |
| 5 | JOIN riêng dòng, ON indent | JOIN clause dòng mới, ON indent bên dưới | LEFT JOIN orders... indent ON ... |
| 6 | Dùng table alias | Alias ngắn gọn, có nghĩa | customers AS c, orders AS o |
| 7 | Luôn dùng AS cho alias | Explicit alias với keyword AS | SUM(amount) AS total thay vì SUM(amount) total |
| 8 | Align dọc | Căn chỉnh AS, ON, toán tử cho dễ đọc | Align các AS cùng cột |
| 9 | Comment giải thích | Comment cho logic phức tạp, business rules | -- Chỉ lấy đơn hàng đã hoàn thành |
| 10 | Trailing semicolon | Kết thúc mỗi query bằng ; | ORDER BY revenue DESC; |
Leading Comma vs Trailing Comma
Hai trường phái phổ biến — chọn một và nhất quán trong team:
Trailing Comma (phổ biến hơn — GitLab, Mozilla recommend):
sql
SELECT
customer_id,
customer_name,
city,
segment
FROM customers;Leading Comma (dbt, một số data teams ưa thích):
sql
SELECT
customer_id
, customer_name
, city
, segment
FROM customers;💡 Leading comma có ưu điểm: dễ comment out 1 cột mà không cần sửa dấu phẩy dòng trước. Nhưng trailing comma tự nhiên hơn và phổ biến hơn. Quan trọng nhất: consistency — cả team dùng chung 1 style.
CTE (Common Table Expression) Formatting
Khi query phức tạp, dùng CTE để chia nhỏ logic:
sql
-- Tính doanh thu theo region, sau đó rank
WITH regional_revenue AS (
SELECT
c.city AS region,
COUNT(DISTINCT o.order_id) AS total_orders,
SUM(o.total_amount) AS total_revenue
FROM customers AS c
INNER JOIN orders AS o
ON c.customer_id = o.customer_id
WHERE o.order_date >= '2026-01-01'
AND o.status = 'completed'
GROUP BY c.city
),
ranked_regions AS (
SELECT
region,
total_orders,
total_revenue,
RANK() OVER (ORDER BY total_revenue DESC) AS revenue_rank
FROM regional_revenue
)
SELECT
region,
total_orders,
total_revenue,
revenue_rank
FROM ranked_regions
WHERE revenue_rank <= 10
ORDER BY revenue_rank;Áp dụng cho Data Analyst
| Tình huống DA | SQL Style Guide áp dụng thế nào |
|---|---|
| Viết query hàng ngày | Format chuẩn → bản thân đọc lại sau 1 tháng vẫn hiểu |
| Gửi query cho team lead review | Code clean → review nhanh, ít comment sửa, tiết kiệm thời gian |
| Debug query lỗi | Mỗi clause 1 dòng → dễ tìm dòng gây lỗi, dễ comment out để test |
| Onboarding thành viên mới | Query có comment + format chuẩn → người mới hiểu logic nhanh hơn |
| Tạo query library / documentation | Consistent naming + formatting → tái sử dụng query dễ dàng |
| Phỏng vấn SQL | Whiteboard coding → query format đẹp thể hiện tư duy có cấu trúc |
Tip thực tế: Sử dụng SQL formatter tools để tự động format: SQLFluff (linter + formatter), DBeaver built-in formatter, hoặc online tools như poorsql.com. Nhưng hãy hiểu rules trước — formatter chỉ hỗ trợ, không thay thế hiểu biết.
Ví dụ thực tế
Tình huống: Cùng một yêu cầu business — "Top 10 khách hàng có doanh thu cao nhất Q1/2026, bao gồm tên, thành phố, số đơn và tổng doanh thu" — nhưng viết theo 2 phong cách khác nhau.
❌ Query không theo Style Guide:
sql
select customer_name,city,count(*) as cnt,sum(total_amount) as rev
from customers c join orders o on c.customer_id=o.customer_id
where order_date between '2026-01-01' and '2026-03-31' and status='completed'
group by customer_name,city order by rev desc limit 10Vấn đề:
- Không viết hoa keywords → khó phân biệt keyword vs tên cột
- Viết trên 1-2 dòng → khó đọc, khó debug
- Alias
cnt,rev→ không rõ nghĩa - Không có comment giải thích business logic
- Thiếu semicolon kết thúc
✅ Query theo Style Guide chuẩn:
sql
-- Top 10 khách hàng doanh thu cao nhất Q1/2026
-- Yêu cầu: Marketing team cần danh sách VIP để gửi chương trình loyalty
SELECT
c.customer_name,
c.city,
COUNT(o.order_id) AS total_orders,
SUM(o.total_amount) AS total_revenue
FROM customers AS c
INNER JOIN orders AS o
ON c.customer_id = o.customer_id
WHERE o.order_date BETWEEN '2026-01-01' AND '2026-03-31'
AND o.status = 'completed'
GROUP BY
c.customer_name,
c.city
ORDER BY total_revenue DESC
LIMIT 10;Cải thiện:
- Keywords UPPERCASE → rõ ràng
- Mỗi clause 1 dòng, cột indent → dễ scan
- Alias descriptive:
total_orders,total_revenue→ tự giải thích - Comment giải thích business context
- Semicolon kết thúc
3️⃣ DAMA DMBOK — Data Modeling Standards
Giới thiệu
DAMA DMBOK (Data Management Body of Knowledge) là bộ kiến thức toàn diện về quản lý dữ liệu, được xuất bản bởi DAMA International (Data Management Association International). DAMA DMBOK 2 (phiên bản mới nhất, 2017) bao gồm 14 knowledge areas, trong đó Data Modeling & Design là knowledge area trọng tâm cho Buổi 5.
Data Modeling là quá trình thiết kế cấu trúc database — quyết định cần bao nhiêu bảng, mỗi bảng có cột gì, kiểu dữ liệu ra sao, và các bảng liên kết với nhau thế nào. Đây chính là bước trước khi viết SQL — nếu database thiết kế tốt, query sẽ đơn giản và hiệu quả; nếu thiết kế kém, query phức tạp, chậm, và dễ sai.
Đối với Data Analyst, bạn thường không tự thiết kế database (đó là việc của Database Developer/DBA), nhưng bạn cần đọc hiểu data model (ERD) để biết dữ liệu nằm ở đâu, bảng nào liên kết với bảng nào, và viết JOIN đúng cách.
Nội dung chính
3 Cấp độ Data Model (DAMA DMBOK Framework)
| Cấp độ | Tên | Mục đích | Audience | Ví dụ |
|---|---|---|---|---|
| Level 1 | Conceptual Data Model | Khái niệm — những entity nào tồn tại và quan hệ ra sao | Business stakeholders | "Customer đặt Order, Order chứa Product" |
| Level 2 | Logical Data Model | Logic — chi tiết hóa attributes, data types, relationships | Data Architect, DA | ERD với cột, kiểu dữ liệu, PK/FK, cardinality |
| Level 3 | Physical Data Model | Vật lý — implement trên database cụ thể | DBA, Developer | CREATE TABLE statements, indexes, partitions |
Level 1: Conceptual Level 2: Logical Level 3: Physical
┌──────────┐ ┌──────────────────┐ CREATE TABLE customers (
│ Customer │──orders──> │ customers │ customer_id INT PRIMARY KEY,
│ │ │ ─ customer_id PK │ customer_name VARCHAR(100),
└──────────┘ │ ─ name VARCHAR │ email VARCHAR(150) UNIQUE,
│ ─ email VARCHAR │ city VARCHAR(50),
┌──────────┐ │ ─ city VARCHAR │ segment VARCHAR(20)
│ Order │ └──────────────────┘ );
└──────────┘💡 Data Analyst làm việc chủ yếu ở Level 2 (Logical) — đọc ERD để hiểu cấu trúc, viết query dựa trên mô hình này.
Normalization — Chuẩn hóa dữ liệu
Normalization là quy trình tổ chức dữ liệu để giảm trùng lặp (redundancy) và đảm bảo tính nhất quán (consistency). DAMA DMBOK khuyến nghị hiểu ít nhất 3 Normal Forms đầu tiên:
| Normal Form | Tên | Quy tắc | Ví dụ vi phạm | Cách sửa |
|---|---|---|---|---|
| 1NF | First Normal Form | Mỗi ô chứa 1 giá trị nguyên tử (atomic), không có repeating groups | Cột phones: "0901234567, 0987654321" | Tách thành bảng customer_phones |
| 2NF | Second Normal Form | 1NF + Mỗi cột non-key phụ thuộc toàn bộ primary key | Trong order_items(order_id, product_id, product_name) — product_name chỉ phụ thuộc product_id | Tách product_name sang bảng products |
| 3NF | Third Normal Form | 2NF + Không có transitive dependency — non-key không phụ thuộc non-key khác | Trong orders(order_id, customer_id, customer_city) — customer_city phụ thuộc customer_id, không phụ thuộc order_id | Tách customer_city sang bảng customers |
Tại sao Normalization quan trọng cho DA?
❌ Database KHÔNG chuẩn hóa (denormalized):
┌─────────────────────────────────────────────────────────────────────────────┐
│ order_id │ customer_name │ customer_city │ product_name │ category │ amount │
│ 1001 │ Nguyễn Văn An │ Hà Nội │ Laptop Dell │ Laptop │ 15tr │
│ 1002 │ Nguyễn Văn An │ Hà Nội │ Chuột Logi │ Phụ kiện │ 500k │
│ 1003 │ Trần Thị Bé │ HCM │ Laptop Dell │ Laptop │ 15tr │
└─────────────────────────────────────────────────────────────────────────────┘
Vấn đề: "Nguyễn Văn An" lặp lại → đổi tên phải sửa NHIỀU dòng
"Laptop Dell" + "Laptop" lặp lại → inconsistency risk
✅ Database chuẩn hóa (3NF):
customers: customer_id │ customer_name │ city
products: product_id │ product_name │ category
orders: order_id │ customer_id │ order_date
order_items: item_id │ order_id │ product_id │ quantity │ unit_price
→ Mỗi thông tin lưu MỘT nơi duy nhất → JOIN khi cầnDAMA Naming Convention cho Database Objects
| Đối tượng | Quy tắc DAMA | Ví dụ | Giải thích |
|---|---|---|---|
| Table | Danh từ, số nhiều, snake_case | customers, order_items | Bảng chứa nhiều records → số nhiều |
| Column | Descriptive, snake_case | customer_name, order_date | Tên phải tự giải thích — đọc tên biết nội dung |
| Primary Key | table_singular_id | customer_id, order_id | Singular form + _id |
| Foreign Key | Trùng tên PK bảng tham chiếu | orders.customer_id → customers.customer_id | Cùng tên giúp nhận biết quan hệ ngay |
| Index | idx_table_column | idx_orders_customer_id | Prefix idx_ |
| View | vw_ prefix hoặc descriptive | vw_monthly_revenue | Phân biệt view vs table |
| Stored Procedure | sp_ prefix | sp_calculate_revenue | Phân biệt procedure |
ERD Notation — Ký hiệu quan hệ
DAMA DMBOK giới thiệu nhiều ERD notation, phổ biến nhất là Crow's Foot (chân quạ):
Crow's Foot Notation:
1-to-1: ──────||──────||────── (hiếm gặp)
1-to-Many: ──────||──────<────── 1 customer → nhiều orders
Many-to-Many: ──────>──────<────── products ↔ orders (qua order_items)
Ký hiệu:
|| = Exactly one (1 và chỉ 1)
O| = Zero or one (0 hoặc 1)
> = Many (nhiều)
O> = Zero or many (0 hoặc nhiều)
Ví dụ thực tế:
customers ||──O>── orders → 1 customer có 0 hoặc nhiều orders
orders ||──|>── order_items → 1 order có 1 hoặc nhiều order_items
products ||──O>── order_items → 1 product xuất hiện trong 0 hoặc nhiều order_itemsÁp dụng cho Data Analyst
| Tình huống DA | DAMA Data Modeling áp dụng thế nào |
|---|---|
| Đọc ERD để hiểu database | Biết đọc Crow's Foot → xác định đúng quan hệ → viết JOIN chính xác |
| Viết JOIN nhiều bảng | Hiểu 1-N vs N-N → tránh duplicate khi JOIN (cartesian product) |
| Thảo luận với Database team | Nói cùng "ngôn ngữ" — conceptual/logical/physical, normalization, cardinality |
| Đề xuất thêm cột/bảng mới | Hiểu normalization → đề xuất đúng cách (tách bảng vs thêm cột) |
| Validate data quality | Data model chuẩn = dễ check constraints, uniqueness, referential integrity |
| Self-service analytics | Hiểu schema → tự tìm data cần thiết mà không phải hỏi DBA mỗi lần |
Tip thực tế: Khi bắt đầu ở công ty mới, việc đầu tiên hãy xin ERD hoặc data dictionary từ team Database/Engineering. Dành 1-2 ngày đọc hiểu model trước khi viết bất kỳ query nào. Điều này tiết kiệm hàng tuần debug query sai vì hiểu nhầm quan hệ giữa các bảng.
Ví dụ thực tế
Tình huống: Data Analyst nhận yêu cầu "Phân tích doanh thu theo danh mục sản phẩm và khu vực". Cần đọc ERD để xác định cần JOIN những bảng nào.
Bước 1: Đọc ERD
customers (customer_id PK, customer_name, city, segment)
||
O>
orders (order_id PK, customer_id FK, order_date, total_amount, status)
||
|>
order_items (item_id PK, order_id FK, product_id FK, quantity, unit_price)
O<
||
products (product_id PK, product_name, category, price)Bước 2: Xác định quan hệ cần JOIN
| Thông tin cần | Nằm ở bảng | JOIN path |
|---|---|---|
| Khu vực (city) | customers | customers → orders |
| Danh mục (category) | products | products → order_items → orders |
| Doanh thu (revenue) | Tính từ order_items | quantity × unit_price |
Bước 3: Viết query theo đúng data model
sql
-- Phân tích doanh thu theo danh mục sản phẩm và khu vực
-- Data model: customers → orders → order_items → products
SELECT
c.city AS region,
p.category AS product_category,
COUNT(DISTINCT o.order_id) AS total_orders,
SUM(oi.quantity * oi.unit_price) AS total_revenue,
AVG(oi.quantity * oi.unit_price) AS avg_line_value
FROM customers AS c
INNER JOIN orders AS o
ON c.customer_id = o.customer_id
INNER JOIN order_items AS oi
ON o.order_id = oi.order_id
INNER JOIN products AS p
ON oi.product_id = p.product_id
WHERE o.status = 'completed'
AND o.order_date >= '2026-01-01'
GROUP BY
c.city,
p.category
ORDER BY
c.city,
total_revenue DESC;4️⃣ Codd's 12 Rules — Nền tảng Relational Database
Giới thiệu
Codd's 12 Rules (thực tế gồm 13 rules, đánh số 0–12) được Edgar F. Codd — "cha đẻ" của relational database — công bố năm 1985 trong bài báo trên tạp chí ComputerWorld. Các rules này định nghĩa một hệ thống quản lý database phải đáp ứng những gì để được gọi là "fully relational".
Đối với Data Analyst, bạn không cần thuộc tất cả 13 rules, nhưng hiểu 5 rules quan trọng nhất giúp bạn nắm được triết lý cốt lõi của relational database — hiểu tại sao data tổ chức theo bảng, tại sao cần key, tại sao dùng SQL chứ không phải cách khác.
Nội dung chính — 5 Rules quan trọng nhất cho DA
| # | Rule | Nội dung | Ý nghĩa cho DA |
|---|---|---|---|
| 0 | Foundation Rule | Hệ thống phải quản lý data hoàn toàn qua relational capabilities | Mọi thao tác đều qua SQL — không cần biết data lưu vật lý thế nào |
| 1 | Information Rule | Tất cả data được biểu diễn dưới dạng bảng (table) | Data luôn ở dạng hàng × cột → bạn luôn query bằng SELECT FROM |
| 2 | Guaranteed Access | Mỗi giá trị data có thể truy cập qua table name + PK + column name | Mọi data đều "tìm được" nếu biết bảng + key + cột |
| 5 | Comprehensive Data Sublanguage | Phải có ít nhất 1 ngôn ngữ hỗ trợ DDL, DML, DCL | Ngôn ngữ đó chính là SQL — 1 ngôn ngữ cho mọi thao tác |
| 10 | Integrity Independence | Integrity constraints (PK uniqueness, FK references) phải được database quản lý, không phải application | PK không trùng, FK phải tồn tại → data quality đảm bảo ở tầng database |
Áp dụng cho Data Analyst
| Rule | DA áp dụng thế nào |
|---|---|
| Information Rule | Mọi data trong DB đều ở dạng bảng → bạn luôn query bảng, JOIN bảng, GROUP BY bảng |
| Guaranteed Access | Biết table + PK + column → truy xuất bất kỳ data nào → self-service analytics |
| Integrity Independence | Database tự đảm bảo PK unique, FK valid → tin tưởng data quality ở mức cấu trúc |
Ví dụ thực tế
sql
-- Codd's Rule #2 — Guaranteed Access:
-- Mọi giá trị đều truy cập được qua: table name + primary key + column name
-- Truy cập tên khách hàng có customer_id = 1001:
SELECT customer_name -- column name
FROM customers -- table name
WHERE customer_id = 1001; -- primary key value
-- Codd's Rule #10 — Integrity Independence:
-- Database tự đảm bảo: primary key không trùng, foreign key phải tồn tại
-- Nếu INSERT order với customer_id không tồn tại → database TỰ reject:
-- INSERT INTO orders (order_id, customer_id, ...)
-- VALUES (9999, 99999, ...); -- ERROR: FK violation nếu customer_id 99999 không tồn tại
-- → Data Analyst tin tưởng rằng mọi order đều có customer hợp lệ5️⃣ ISO/IEC 11179 — Metadata & Naming Standards
Giới thiệu
ISO/IEC 11179 là tiêu chuẩn quốc tế về Metadata Registry — quy định cách đặt tên, định nghĩa, và quản lý các data element (cột, bảng, thuộc tính) trong hệ thống thông tin. Phiên bản hiện hành là ISO/IEC 11179-5:2015.
Tiêu chuẩn này quan trọng vì một vấn đề phổ biến trong doanh nghiệp: cùng một khái niệm business nhưng mỗi team đặt tên khác nhau. Team Sales gọi là Revenue, team Finance gọi là Net_Sales, team Data gọi là total_amount — gây confusion khi phân tích cross-functional.
Nội dung chính
Cấu trúc đặt tên Data Element (ISO 11179)
Mỗi data element name gồm 3 phần:
| Thành phần | Mô tả | Ví dụ |
|---|---|---|
| Object | Đối tượng / Entity | customer, order, product |
| Property | Thuộc tính | name, date, amount, count |
| Representation | Kiểu biểu diễn | _text, _date, _amount, _code, _id |
Ví dụ áp dụng:
customer_name → Object: customer + Property: name
order_date → Object: order + Property: date
product_category → Object: product + Property: category
total_amount → Object: total + Property: amount
customer_id → Object: customer + Representation: idBusiness Glossary — Từ điển data thống nhất
ISO 11179 khuyến nghị tạo Business Glossary để thống nhất định nghĩa:
| Thuật ngữ | Định nghĩa business | Tên trong DB | Kiểu dữ liệu | Bảng |
|---|---|---|---|---|
| Revenue | Tổng tiền hàng bán được (chưa trừ chi phí) | total_amount | DECIMAL(15,2) | orders |
| Order Count | Số đơn hàng hoàn thành | COUNT(order_id) | Calculated | orders |
| Customer Segment | Phân nhóm KH: Premium / Standard / Basic | segment | VARCHAR(20) | customers |
| Product Category | Nhóm sản phẩm chính | category | VARCHAR(50) | products |
| AOV | Average Order Value — giá trị trung bình mỗi đơn | AVG(total_amount) | Calculated | orders |
Áp dụng cho Data Analyst
| Tình huống DA | ISO 11179 áp dụng thế nào |
|---|---|
| Đặt tên alias trong query | Dùng convention Object_Property: total_revenue, order_count |
| Tạo report / dashboard | Dùng Business Glossary để thống nhất terminology |
| Giao tiếp cross-team | "Revenue" nghĩa là gì? → check glossary → tránh hiểu nhầm |
| Tạo data dictionary | Mỗi cột có: tên, định nghĩa, kiểu, ví dụ → documentation chuẩn |
Ví dụ thực tế
❌ Naming không theo chuẩn — gây confusion:
sql
SELECT
nm, -- nm là gì? name? number?
dt, -- dt là gì? date? data?
amt, -- amt là gì? amount? amendment?
tp -- tp là gì? type? top?
FROM tbl_cust; -- tbl_cust — prefix tbl_ không cần thiết✅ Naming theo ISO 11179 — tự giải thích:
sql
SELECT
customer_name, -- Object: customer, Property: name
order_date, -- Object: order, Property: date
total_amount, -- Object: total, Property: amount
product_category -- Object: product, Property: category
FROM customers;🎓 Chứng chỉ liên quan
Lộ trình chứng chỉ cho SQL & Database
Beginner (0-3 tháng)
→ Google Data Analytics Certificate (Course 3-4: Prepare + Process — SQL basics)
→ HackerRank SQL (Basic) Certificate — miễn phí
→ W3Schools SQL Certificate
Intermediate (3-6 tháng)
→ HackerRank SQL (Intermediate) Certificate
→ DataCamp SQL Associate Certificate
→ Oracle Database SQL Certified Associate (1Z0-071)
Advanced (6-12 tháng)
→ HackerRank SQL (Advanced) Certificate
→ DataCamp SQL Professional Certificate
→ Microsoft Azure Data Fundamentals (DP-900)
→ CDMP (Certified Data Management Professional) — DAMA International
→ Read: "SQL for Data Scientists" — Renee Teate
→ Read: "Learning SQL" — Alan Beaulieu (O'Reilly)So sánh chi tiết
| Tiêu chí | Google DA Cert | HackerRank SQL | Oracle SQL Associate | CDMP (DAMA) |
|---|---|---|---|---|
| SQL depth | ⭐⭐ Basics — SELECT, JOIN, GROUP BY | ⭐⭐⭐ Problem-solving — queries thực tế | ⭐⭐⭐ Deep — subqueries, window functions | ⭐⭐ Concepts — data modeling, theory |
| Data Modeling | ⭐ Concepts only | ⭐ Không focus | ⭐⭐ ERD, normalization | ⭐⭐⭐ Core — DMBOK framework |
| Hands-on practice | ⭐⭐ BigQuery | ⭐⭐⭐ Online judge | ⭐⭐⭐ Oracle DB | ⭐ Theory-focused |
| Industry recognition | Google + many employers | Tech companies | Enterprise / Oracle shops | Data governance roles |
| Cost | ~$49/month (Coursera) | Miễn phí | ~$245 | ~$411 |
| Phù hợp nhất | Career starters | Practice + portfolio | DB-heavy DA roles | Data management roles |
🔗 Ma trận tiêu chuẩn × Chủ đề buổi học
| Chủ đề Buổi 5 | ANSI SQL | SQL Style Guide | DAMA Data Modeling | Codd's Rules | ISO 11179 Naming |
|---|---|---|---|---|---|
| Relational Database concepts | ⭐⭐ SQL là ngôn ngữ của RDBMS | ⭐ Naming cho DB objects | ⭐⭐⭐ Core — table, key, relationship | ⭐⭐⭐ Nền tảng lý thuyết RDBMS | ⭐⭐ Naming data elements |
| SELECT query | ⭐⭐⭐ Core — DQL chuẩn ANSI | ⭐⭐⭐ Format SELECT clause | ⭐ Biết query từ bảng nào | ⭐⭐ Information Rule — query bảng | ⭐⭐ Alias naming convention |
| WHERE & filtering | ⭐⭐⭐ WHERE, BETWEEN, IN, LIKE | ⭐⭐⭐ Indent điều kiện, AND/OR | ⭐ Filter đúng bảng | ⭐⭐ Guaranteed Access | ⭐ Không trực tiếp |
| JOIN (INNER, LEFT, RIGHT, FULL) | ⭐⭐⭐ ANSI JOIN syntax (SQL-92) | ⭐⭐⭐ JOIN formatting, ON clause | ⭐⭐⭐ Core — PK/FK, relationship, cardinality | ⭐⭐ Data in tables, joined by keys | ⭐⭐ FK naming = PK naming |
| GROUP BY & Aggregation | ⭐⭐⭐ GROUP BY + HAVING chuẩn | ⭐⭐⭐ GROUP BY formatting | ⭐⭐ Aggregate trên normalized tables | ⭐ Không trực tiếp | ⭐⭐ Alias cho calculated columns |
| Aggregate functions | ⭐⭐⭐ COUNT, SUM, AVG, MIN, MAX | ⭐⭐ Alias conventions | ⭐⭐ Biết aggregate trên cột nào | ⭐ Không trực tiếp | ⭐⭐ Naming calculated metrics |
| Primary Key & Foreign Key | ⭐⭐ Constraint syntax | ⭐⭐ PK/FK naming convention | ⭐⭐⭐ Core — entity identity, relationships | ⭐⭐⭐ Rule #2, #10 | ⭐⭐⭐ Object_id naming |
| ERD (Entity Relationship Diagram) | ⭐ Không trực tiếp | ⭐ Không trực tiếp | ⭐⭐⭐ Core — Crow's Foot notation | ⭐⭐ Visual representation of rules | ⭐⭐ Object naming in ERD |
| Data types | ⭐⭐⭐ INT, VARCHAR, DATE, DECIMAL | ⭐ Không trực tiếp | ⭐⭐⭐ Logical data model → data types | ⭐ Không trực tiếp | ⭐⭐ Representation term |
Chú thích: ⭐ = Liên quan gián tiếp | ⭐⭐ = Liên quan trực tiếp | ⭐⭐⭐ = Core/trọng tâm
📝 Checklist áp dụng cho Data Analyst
Trước khi viết Query
- [ ] Hiểu yêu cầu business: Query này trả lời câu hỏi gì? Ai sẽ dùng kết quả?
- [ ] Đọc ERD / Data Dictionary: Xác định data nằm ở bảng nào, quan hệ giữa các bảng ra sao
- [ ] Xác định JOIN path: Từ bảng A sang bảng B qua key nào? Có cần bảng trung gian không?
- [ ] Chọn JOIN type: INNER JOIN (chỉ khớp), LEFT JOIN (giữ tất cả bảng trái), hay FULL JOIN?
- [ ] Sketch kết quả mong muốn: Hình dung output sẽ có những cột gì, bao nhiêu dòng?
Khi viết Query
- [ ] ANSI SQL syntax: Dùng explicit JOIN (không implicit), keywords UPPERCASE
- [ ] Naming convention: Alias có nghĩa (
total_revenue, không phảitr), snake_case - [ ] Format chuẩn: Mỗi clause 1 dòng, cột indent, ON indent dưới JOIN
- [ ] Comment business logic: Giải thích WHY, không giải thích WHAT (code đã nói WHAT)
- [ ] NULL awareness: Dùng
COUNT(column)vsCOUNT(*)đúng ngữ cảnh, hiểuAVG()bỏ qua NULL - [ ] Tránh
SELECT *: Chỉ SELECT cột cần thiết — performance tốt hơn, output rõ hơn - [ ] Semicolon: Kết thúc mỗi query bằng
;
Khi viết GROUP BY & Aggregation
- [ ] Mọi cột non-aggregate trong SELECT phải có trong GROUP BY — quy tắc ANSI SQL
- [ ] Phân biệt WHERE vs HAVING: WHERE lọc dòng trước GROUP BY, HAVING lọc nhóm sau GROUP BY
- [ ] Alias descriptive:
SUM(amount) AS total_revenue, không phảiSUM(amount) AS s1 - [ ] COUNT đúng cách:
COUNT(*)đếm dòng,COUNT(column)bỏ NULL,COUNT(DISTINCT column)đếm unique
Sau khi viết Query
- [ ] Validate kết quả: Chạy thử, kiểm tra số dòng, tổng số, spot-check vài dòng
- [ ] Cross-check: So sánh kết quả với nguồn khác (Excel, report cũ) — có khớp không?
- [ ] Performance: Query có chạy trong thời gian hợp lý? Có cần thêm WHERE filter?
- [ ] Duplicate check: JOIN có gây duplicate dòng không? (Đặc biệt khi JOIN bảng 1-N)
- [ ] Format review: Đọc lại query — người khác có hiểu không? Comment đủ chưa?
- [ ] Save & document: Lưu query có tên file rõ ràng, ghi chú business context
SQL Code Style Checklist
- [ ] Keywords: Tất cả SQL keywords viết HOA (
SELECT,FROM,WHERE,JOIN,GROUP BY) - [ ] Table names: snake_case, số nhiều (
customers,order_items) - [ ] Column names: snake_case, descriptive (
customer_name,order_date) - [ ] Aliases: Luôn dùng
AS, alias có nghĩa (AS total_revenue) - [ ] Indentation: 4 spaces cho cột, điều kiện, ON clause
- [ ] JOIN: Explicit
INNER JOIN/LEFT JOIN(không implicit) - [ ] No
SELECT *: Liệt kê rõ cột cần thiết - [ ] Comments: Giải thích business context ở đầu query
📚 Tài liệu tham khảo
Tiêu chuẩn chính thức
- ISO/IEC 9075:2023 — Information technology — Database languages — SQL — iso.org
- DAMA DMBOK 2nd Edition (2017) — Data Management Body of Knowledge — DAMA International — dama.org
- ISO/IEC 11179-5:2015 — Information technology — Metadata registries — iso.org
- Codd, E.F. (1970) — "A Relational Model of Data for Large Shared Data Banks", Communications of the ACM
SQL Style Guides
- Simon Holywell's SQL Style Guide — sqlstyle.guide — Phổ biến nhất, dựa trên Joe Celko's work
- GitLab SQL Style Guide — handbook.gitlab.com — Practical, production-tested
- Mozilla SQL Style Guide — docs.telemetry.mozilla.org — BigQuery-focused
- dbt SQL Style Guide — docs.getdbt.com — Analytics engineering
Sách kinh điển
- Beaulieu, A. (2020) — "Learning SQL", 3rd Edition, O'Reilly — Sách nhập môn SQL kinh điển
- Teate, R. (2021) — "SQL for Data Scientists", Wiley — SQL hướng Data Analyst/Scientist
- Molinaro, A. (2020) — "SQL Cookbook", 2nd Edition, O'Reilly — Recipes cho mọi tình huống
- Celko, J. (2005) — "Joe Celko's SQL Programming Style", Morgan Kaufmann — SQL coding conventions gốc
- Date, C.J. (2019) — "An Introduction to Database Systems", 8th Edition, Pearson — Lý thuyết RDBMS
Bài viết & Nghiên cứu
- Codd, E.F. (1985) — "Is Your DBMS Really Relational?" and "Does Your DBMS Run By the Rules?", ComputerWorld — Codd's 12 Rules
- Chamberlin, D. & Boyce, R. (1974) — "SEQUEL: A Structured English Query Language", IBM Research — Bài báo gốc về SQL
- "SQL: 2023" — Wikipedia — Tổng hợp các phiên bản ANSI SQL và tính năng mới
Tài liệu online & Practice
- W3Schools SQL Tutorial — w3schools.com/sql — Tutorial cơ bản, interactive
- SQLBolt — sqlbolt.com — Interactive SQL lessons
- Mode Analytics SQL Tutorial — mode.com/sql-tutorial — SQL cho analytics
- LeetCode Database Problems — leetcode.com/problemset/database — Practice SQL problems
- HackerRank SQL — hackerrank.com/domains/sql — SQL challenges + certification
- SQLFluff — sqlfluff.com — SQL linter & formatter
- DB Fiddle — db-fiddle.com — Online SQL sandbox
- PostgreSQL Documentation — postgresql.org/docs — Reference cho PostgreSQL
Video & Courses
- Google Data Analytics Certificate — Course 3 & 4 — SQL Basics — Coursera
- DataCamp — Introduction to SQL — datacamp.com — Interactive SQL course
- freeCodeCamp — SQL Tutorial — youtube.com — Full SQL course (4+ hours)
- Alex the Analyst — SQL for Beginners — YouTube playlist — Practical DA-focused SQL tutorials
🔗 Xem thêm Buổi 5
→ 📘 Nội dung chính → 📝 Blog → 🧠 Case Study → 🛠 Workshop → 🎮 Mini Game