Mở đầu — vì sao bài này quan trọng
Nếu bạn đến từ Finance hay Kế toán, có một sự thật ít người nói thẳng với bạn: bạn đã làm việc với data model suốt nhiều năm rồi, chỉ là bạn gọi nó bằng tên khác. Bảng cân đối tài khoản (Chart of Accounts), sổ cái tổng hợp (General Ledger), sổ chi tiết (sub-ledger), bảng kê công nợ phải thu/phải trả — tất cả đều là những cấu trúc dữ liệu được thiết kế chặt chẽ, có quan hệ rõ ràng, có ràng buộc nghiêm ngặt. Cái mà dân IT gọi là "data model" thì bản chất chính là tư duy bạn đã dùng mỗi ngày khi đối chiếu số dư.
ERD — Entity Relationship Diagram (Sơ đồ quan hệ thực thể) — là ngôn ngữ mà BA dùng để mô tả cấu trúc dữ liệu của một hệ thống trước khi developer xây nó. Nó trả lời câu hỏi: hệ thống cần lưu những loại dữ liệu nào, mỗi loại có những thuộc tính gì, và chúng liên kết với nhau ra sao. Đây là một trong những deliverable quan trọng nhất của BA, vì nếu data model sai thì cả phần mềm xây trên nó sẽ sai theo, và việc sửa sau khi đã đi vào vận hành cực kỳ tốn kém.
Tin tốt cho bạn: trong số các kỹ năng kỹ thuật mà một ex-Finance phải học, ERD là thứ bạn tiếp thu nhanh nhất. Lý do là tư duy "mọi giao dịch phải khớp, mọi số liệu phải có nguồn gốc và quan hệ" của kế toán ánh xạ gần như 1:1 sang tư duy chuẩn hóa dữ liệu (normalization) trong thiết kế cơ sở dữ liệu. Bài này sẽ giúp bạn tận dụng tối đa lợi thế đó.
Khái niệm cốt lõi
Ba thành phần của một ERD
Một ERD chỉ có ba thứ bạn cần nắm: Entity (thực thể), Attribute (thuộc tính), và Relationship (quan hệ).
Entity (Thực thể) là một "loại đối tượng" mà hệ thống cần lưu trữ thông tin về nó. Trong thực tế, mỗi entity thường tương ứng với một bảng (table) trong cơ sở dữ liệu. Ví dụ: Khách hàng (Customer), Hóa đơn (Invoice), Tài khoản kế toán (Account), Giao dịch (Transaction). Mẹo nhận diện: entity thường là danh từ, và bạn có thể đếm được nhiều "bản" của nó (nhiều khách hàng, nhiều hóa đơn).
Attribute (Thuộc tính) là các đặc điểm mô tả một entity. Entity Khách hàng có các attribute: mã khách hàng, họ tên, số điện thoại, mã số thuế, hạn mức công nợ. Mỗi attribute tương ứng với một cột (column) trong bảng.
Có hai loại attribute đặc biệt mà người Finance phải hiểu rất kỹ:
- Primary Key (Khóa chính): thuộc tính định danh duy nhất một bản ghi. Giống như mỗi tài khoản trong Chart of Accounts có một mã số duy nhất (ví dụ 131 — Phải thu khách hàng), mỗi entity cần một khóa chính để không bị nhầm lẫn. Mã khách hàng chính là khóa chính của entity Customer.
- Foreign Key (Khóa ngoại): thuộc tính dùng để "trỏ" sang một entity khác, tạo nên mối quan hệ. Khi một hóa đơn ghi "khách hàng KH001", thì cột mã khách hàng trong bảng Hóa đơn chính là foreign key trỏ về bảng Khách hàng. Đây chính xác là logic của bút toán có tài khoản đối ứng — mỗi dòng đều "trỏ" về một đối tượng cụ thể.
- 1:1 (một-một): một nhân viên có một hợp đồng lao động chính.
- 1:N (một-nhiều): một khách hàng có nhiều hóa đơn; nhưng mỗi hóa đơn chỉ thuộc về một khách hàng. Đây là quan hệ phổ biến nhất.
- N:M (nhiều-nhiều): một hóa đơn có nhiều sản phẩm, và một sản phẩm xuất hiện trên nhiều hóa đơn. Quan hệ này luôn cần một bảng trung gian để giải quyết (gọi là junction table hoặc associative entity).
Ký hiệu Crow's Foot — thứ bạn sẽ vẽ thật
Trong thực tế ngành, ký hiệu được dùng nhiều nhất là Crow's Foot Notation (ký hiệu chân quạ), vì nó trực quan và dễ đọc. Bạn cần thuộc các ký hiệu ở đầu mỗi đường nối:
- Một gạch thẳng "|" = "một" (one)
- Hình chân quạ "<" (ba nhánh tỏa ra) = "nhiều" (many)
- Vòng tròn "O" = "không hoặc" (optional, có thể bằng 0)
Liên hệ với schema kế toán bạn đã quen
Hãy nhìn sổ sách kế toán như một data model đã được thiết kế sẵn:
| Khái niệm kế toán | Tương đương trong ERD |
|---|---|
| Chart of Accounts (hệ thống tài khoản) | Entity Account với khóa chính là mã tài khoản |
| General Ledger (sổ cái) | Entity JournalEntry (bút toán) |
| Một dòng bút toán Nợ/Có | Entity JournalLine, foreign key trỏ về Account |
| Sub-ledger (sổ chi tiết công nợ) | Entity con liên kết 1:N với entity tổng hợp |
| Quan hệ "một hóa đơn nhiều dòng hàng" | Quan hệ 1:N giữa Invoice và InvoiceLine |
JournalEntry và JournalLine mà không cần ai dạy.Tình huống thực tế
Tình huống 1 — Hằng và hệ thống quản lý công nợ tại một công ty phân phối FMCG
Hằng từng là kế toán công nợ tại một nhà phân phối hàng tiêu dùng ở Bình Dương, quản lý khoảng 400 đại lý. Sau khi chuyển sang làm BA, dự án đầu tiên của cô là số hóa quy trình theo dõi công nợ vốn đang nằm trên một file Excel 12.000 dòng.
Khi PM yêu cầu vẽ data model, Hằng đã làm điều mà nhiều ex-Finance làm theo bản năng: cô nhìn vào file Excel và thấy nó "phẳng" — mỗi dòng có cả tên đại lý, địa chỉ, số hóa đơn, ngày, số tiền, đã trả, còn nợ. Ban đầu cô định tạo một entity duy nhất chứa tất cả. Nhưng nhờ tư duy kế toán, cô nhận ra vấn đề: cùng một đại lý "Tạp hóa Minh Tâm" được gõ tay 37 lần với 4 cách viết địa chỉ khác nhau — đúng kiểu sai lệch khiến đối chiếu công nợ luôn lệch.
Cô tách thành ba entity: Đại lý (mã đại lý là khóa chính, lưu thông tin một lần duy nhất), Hóa đơn (foreign key trỏ về đại lý, quan hệ 1:N), và Thanh toán (foreign key trỏ về hóa đơn). Khi vẽ ra, sếp cũ của cô — kế toán trưởng — gật đầu ngay vì nó phản ánh đúng cách họ tư duy: một đại lý, nhiều hóa đơn, mỗi hóa đơn nhiều lần thanh toán.
Bài học: Sai lầm phổ biến nhất của người mới là gom mọi thứ vào một bảng phẳng giống Excel. Tư duy "một thông tin chỉ nên lưu một chỗ" của kế toán (giống nguyên tắc một nghiệp vụ một nguồn gốc) chính là nguyên tắc chuẩn hóa dữ liệu. Tách entity ra để tránh trùng lặp và sai lệch.
Tình huống 2 — Quan hệ N:M tại một ví điện tử fintech
Một bạn ex-kiểm toán làm BA tại một công ty ví điện tử ở TP.HCM được giao thiết kế tính năng "chương trình khuyến mãi": mỗi chương trình khuyến mãi áp dụng cho nhiều người dùng, và mỗi người dùng đủ điều kiện tham gia nhiều chương trình cùng lúc.
Bạn ấy ban đầu vẽ quan hệ trực tiếp giữa entity NgườiDùng và entity KhuyếnMãi bằng một đường nối nhiều-nhiều. Developer phản hồi ngay: "Quan hệ N:M không thể triển khai trực tiếp được, cần bảng trung gian." Bạn ấy bổ sung entity thứ ba NgườiDùng_KhuyếnMãi, lưu: mã người dùng (foreign key), mã khuyến mãi (foreign key), ngày tham gia, số lần đã sử dụng, trạng thái. Bảng trung gian này đồng thời giải quyết luôn yêu cầu nghiệp vụ "mỗi người chỉ được dùng ưu đãi tối đa 3 lần" — vì giờ đã có chỗ để lưu số lần sử dụng.
Bài học: Mọi quan hệ nhiều-nhiều trong thực tế đều cần một entity trung gian. Và entity trung gian thường là nơi chứa những attribute nghiệp vụ quan trọng nhất (ngày tham gia, số lần dùng, hạn mức) — giống như sổ chi tiết theo từng đối tượng trong kế toán. Khi bạn thấy "mỗi bên đều có nhiều bên kia", hãy lập tức nghĩ đến bảng trung gian.
Tình huống 3 — Nhầm lẫn giữa attribute và entity tại một startup ERP
Tại một startup làm phần mềm ERP cho doanh nghiệp vừa và nhỏ, một BA mới đặt "phương thức thanh toán" (tiền mặt, chuyển khoản, thẻ) làm một attribute dạng text tự do trong bảng HóaĐơn. Sau ba tháng, dữ liệu xuất hiện đủ kiểu: "tien mat", "TM", "Tiền mặt", "cash". Báo cáo doanh thu theo phương thức thanh toán không gom nhóm được, giống hệt cơn ác mộng khi Chart of Accounts không được chuẩn hóa.
Giải pháp: tách PhươngThứcThanhToán thành một entity riêng (một danh mục có mã cố định), và bảng HóaĐơn chỉ lưu foreign key trỏ về nó. Đây chính là logic của bảng danh mục tài khoản — bạn không gõ tay tên tài khoản vào từng bút toán, bạn chọn từ một danh mục chuẩn.
Bài học: Khi một thuộc tính có tập giá trị giới hạn và lặp lại nhiều lần (danh mục), hãy cân nhắc tách nó thành entity danh mục riêng. Đây là phản xạ mà dân Finance có sẵn từ việc dùng hệ thống tài khoản chuẩn.
Hướng dẫn từng bước
Đây là quy trình thực tế để xây một ERD từ một yêu cầu nghiệp vụ:
Bước 1 — Đọc mô tả nghiệp vụ và gạch chân danh từ. Lấy tài liệu yêu cầu hoặc biên bản phỏng vấn stakeholder, gạch chân mọi danh từ. "Khách hàng đặt đơn hàng, mỗi đơn hàng gồm nhiều sản phẩm, được giao bởi một nhân viên giao hàng." Các danh từ Khách hàng, Đơn hàng, Sản phẩm, Nhân viên giao hàng là ứng viên entity.
Bước 2 — Lọc entity thật sự. Không phải danh từ nào cũng là entity. Hỏi: "Tôi có cần lưu nhiều bản ghi của thứ này với các thuộc tính riêng không?" Nếu có, đó là entity. Nếu nó chỉ là một thuộc tính mô tả (ví dụ "màu sắc"), nó là attribute.
Bước 3 — Xác định attribute cho từng entity. Liệt kê các thuộc tính. Đánh dấu khóa chính (PK) cho mỗi entity — thứ định danh duy nhất.
Bước 4 — Xác định quan hệ và cardinality. Với từng cặp entity, hỏi hai câu: "Một A liên kết với bao nhiêu B?" và ngược lại "Một B liên kết với bao nhiêu A?". Hai câu trả lời ghép lại cho bạn cardinality. Dùng đúng cách diễn giải nghiệp vụ kiểu kế toán: "một khách hàng có thể không có hóa đơn nào hoặc có nhiều hóa đơn".
Bước 5 — Xử lý quan hệ N:M. Mỗi khi gặp nhiều-nhiều, tạo bảng trung gian. Đặt vào đó hai foreign key và mọi attribute mô tả chính mối quan hệ.
Bước 6 — Vẽ bằng công cụ. Các công cụ phổ biến năm 2026: draw.io (miễn phí, dùng nhiều nhất ở VN), Lucidchart, dbdiagram.io (gõ code ra sơ đồ, rất nhanh), hoặc Mermaid trong Confluence. Với BA mới, draw.io và dbdiagram.io là lựa chọn tốt nhất.
Bước 7 — Rà soát với stakeholder và developer. Đưa ERD cho người am hiểu nghiệp vụ để kiểm tra logic, và cho developer để kiểm tra tính khả thi kỹ thuật. ERD là tài liệu giao tiếp, không phải bài tập về nhà.
Lỗi thường gặp & mẹo
Lỗi 1 — Bảng phẳng kiểu Excel. Gom tất cả vào một entity vì quen nhìn file Excel. Mẹo: nếu một giá trị bị lặp lại trên nhiều dòng (tên khách hàng, địa chỉ), nó nên được tách ra thành entity riêng.
Lỗi 2 — Quên cardinality. Vẽ đường nối giữa hai entity nhưng không ghi rõ một-nhiều hay nhiều-nhiều. Đây là thông tin quan trọng nhất của một quan hệ. Luôn luôn ghi.
Lỗi 3 — Để N:M không có bảng trung gian. Developer sẽ trả lại ngay. Hãy tự giải quyết trước khi đưa.
Lỗi 4 — Nhầm attribute thành entity và ngược lại. "Trạng thái đơn hàng" thường là attribute, không cần làm entity (trừ khi cần lưu lịch sử chuyển trạng thái). Ngược lại "phương thức thanh toán" nếu là danh mục cố định thì nên tách entity.
Lỗi 5 — Bỏ qua khóa chính. Mỗi entity bắt buộc phải có cách định danh duy nhất. Đừng giả định "tên là đủ" — hai khách hàng có thể trùng tên.
Mẹo tận dụng nền Finance: Khi bí, hãy tự hỏi "nếu đây là sổ kế toán thì nghiệp vụ này được ghi như thế nào?". Tư duy đối chiếu, tư duy nguồn gốc dữ liệu, tư duy danh mục chuẩn của bạn đều ánh xạ trực tiếp sang thiết kế dữ liệu tốt. Đừng đánh giá thấp lợi thế này.
Bài tập thực hành
Đề bài: Một phòng khám nha khoa nhỏ ở Hà Nội muốn số hóa việc quản lý lịch hẹn. Mô tả nghiệp vụ: "Bệnh nhân đặt lịch hẹn với bác sĩ. Mỗi lịch hẹn thuộc về một bệnh nhân và một bác sĩ, diễn ra vào một khung giờ. Trong mỗi lần khám, bác sĩ có thể chỉ định nhiều dịch vụ (cạo vôi, trám răng, nhổ răng), và mỗi dịch vụ có một bảng giá cố định. Cuối buổi khám hệ thống xuất một hóa đơn cho bệnh nhân."
Yêu cầu:
- Liệt kê các entity (gạch chân danh từ trước).
- Với mỗi entity, ghi ít nhất 3 attribute và đánh dấu khóa chính.
- Vẽ quan hệ và ghi cardinality cho từng cặp.
- Chỉ ra (các) quan hệ N:M và thiết kế bảng trung gian cho nó.
- Vẽ hoàn chỉnh bằng draw.io hoặc dbdiagram.io.
LầnKhám_DịchVụ chứa thêm attribute như số lượng và đơn giá tại thời điểm khám. Nếu bạn liên tưởng được đến cách một hóa đơn bán hàng có nhiều dòng hàng, bạn đã làm đúng.Tóm tắt
ERD là cách BA mô tả cấu trúc dữ liệu của hệ thống, gồm ba thành phần: Entity (thực thể, thường là bảng), Attribute (thuộc tính, thường là cột, với khóa chính và khóa ngoại), và Relationship (quan hệ, với cardinality một-một, một-nhiều, nhiều-nhiều). Người đến từ Finance/Kế toán có lợi thế tự nhiên vì sổ sách kế toán — Chart of Accounts, General Ledger, sub-ledger — chính là những data model được thiết kế chặt chẽ, và tư duy chuẩn hóa, đối chiếu, danh mục chuẩn ánh xạ trực tiếp sang thiết kế dữ liệu tốt.
Hãy nhớ ba phản xạ quan trọng nhất: tách dữ liệu lặp lại thành entity riêng (tránh bảng phẳng kiểu Excel), luôn ghi cardinality cho mọi quan hệ, và luôn thêm bảng trung gian cho quan hệ nhiều-nhiều. Khi bí, hãy tự hỏi nghiệp vụ này được ghi sổ như thế nào — nền tảng Finance của bạn là người thầy thầm lặng nhưng đáng tin cậy nhất. Bài tiếp theo về Compliance & Audit BA sẽ cho bạn thấy một lợi thế tự nhiên khác còn lớn hơn nữa.