DHDataHọc
Lý thuyếtBài 3/305 phút đọc+10 XP

Câu lệnh SELECT đầu tiên

Bạn sẽ học được

  • Cấu trúc đầy đủ của một câu SELECT và thứ tự các mệnh đề.
  • Chạy SELECT * để xem toàn bộ bảng, và biết khi nào nên tránh nó.
  • Vì sao thứ tự dòng trong kết quả không đáng tin nếu thiếu ORDER BY.
  • Đọc kết quả trả về như một bảng thật: tên cột, kiểu giá trị, dòng trống.
  • Hoàn thành bài luyện đầu tiên: lấy toàn bộ khách hàng theo id.

Khái niệm cốt lõi

Mọi truy vấn đọc dữ liệu đều xoay quanh SELECT. Cấu trúc đầy đủ của nó, theo đúng thứ tự bạn viết:

code
SELECT   <cột muốn lấy>
FROM     <bảng nguồn>
WHERE    <điều kiện lọc>       -- tuỳ chọn
ORDER BY <cột sắp xếp>         -- tuỳ chọn
LIMIT    <số dòng tối đa>;     -- tuỳ chọn

Điều thú vị: thứ tự bạn viết không phải thứ tự máy thực thi. Máy đọc FROM trước để biết lấy dữ liệu từ đâu, rồi WHERE để lọc, rồi SELECT để chọn cột, rồi ORDER BY, cuối cùng LIMIT. Hiểu thứ tự này sẽ giúp bạn tránh một lỗi rất phổ biến: dùng bí danh vừa đặt trong SELECT ở mệnh đề WHERE. Lúc WHERE chạy, bí danh đó chưa tồn tại.

Kết quả của SELECT là một bảng tạm (result set): có tên cột, có dòng, có kiểu dữ liệu. Bạn có thể tưởng tượng nó như một bảng mới sinh ra trong bộ nhớ. Điều này quan trọng vì nhiều kỹ thuật nâng cao — subquery, CTE, view — chỉ là đặt một result set vào chỗ của một bảng.

Dấu * nghĩa là "mọi cột". Nó tiện khi khám phá, nhưng có ba nhược điểm: kéo về dữ liệu bạn không dùng, không rõ ý định truy vấn, và dễ vỡ khi ai đó thêm cột vào bảng. Quy tắc thực tế: * để xem, danh sách cột để dùng.

Cuối cùng, một sự thật ít người mới biết: SQL không hứa thứ tự dòng nếu bạn không yêu cầu. Cùng một câu SELECT * FROM customers;, hôm nay có thể trả về An trước Bình, mai có thể khác — nhất là khi bảng lớn và có nhiều CPU. Nếu kết quả cần ổn định (báo cáo, so sánh, chấm bài), luôn thêm ORDER BY.

Ví dụ chạy được

Lấy toàn bộ khách hàng:

code
SELECT *
FROM customers;

Kết quả có 12 dòng. Dưới đây là toàn bộ, để bạn thấy dữ liệu thật trông như thế nào:

idnameemailcitysignup_datesegment
1An Nguyễnan@example.comHà Nội2023-03-12retail
2Bình Trầnbinh@example.comTP. Hồ Chí Minh2023-07-01vip
3Chi Lêchi@example.comĐà Nẵng2024-01-15retail
4Dũng Phạm(NULL)Hà Nội2024-02-20wholesale
5Em Võem@example.comTP. Hồ Chí Minh2024-05-05retail
6Giang Đặnggiang@example.comCần Thơ2024-08-18vip
7Hà Bùiha@example.comHải Phòng2024-11-02retail
8Inh Đỗ(NULL)TP. Hồ Chí Minh2025-01-10retail
9Khánh Hồkhanh@example.comHà Nội2025-02-14wholesale
10Linh Ngôlinh@example.comĐà Nẵng2025-03-09retail
11Minh Dươngminh@example.comCần Thơ2025-04-21vip
12Nga Lýnga@example.comTP. Hồ Chí Minh2025-06-30retail

Ba điều đáng chú ý trong bảng này:

  • Hai khách (Dũng, Inh) không có email — đây là NULL, không phải chuỗi rỗng.
  • Cột signup_date hiển thị dạng 2023-03-12 (năm-tháng-ngày), chuẩn ISO. Đây là cách an toàn nhất để đọc ngày, tránh nhầm giữa 03/12 kiểu Mỹ và kiểu Việt.
  • Cột segment phân loại khách: retail, vip, wholesale.

Bây giờ thêm ORDER BY:

code
SELECT id, name, city
FROM customers
ORDER BY id;

Kết quả giống bảng trên nhưng chỉ ba cột và chắc chắn xếp từ id 1 đến 12. Thử đổi thành ORDER BY name; — bạn sẽ thấy thứ tự theo bảng chữ cái. Với tiếng Việt, PostgreSQL sắp xếp theo collation của database, nên đừng ngạc nhiên nếu thứ tự hơi khác so với trực giác: dấu tiếng Việt ảnh hưởng đến vị trí.

Thử một truy vấn có LIMIT:

code
SELECT id, name
FROM customers
ORDER BY signup_date DESC
LIMIT 3;

Kết quả là ba khách đăng ký gần đây nhất: Nga Lý (2025-06-30), Minh Dương (2025-04-21), Linh Ngô (2025-03-09). Lưu ý DESC — sắp xếp giảm dần. Mặc định là ASC (tăng dần). Khi cần "mới nhất", "lớn nhất", "đắt nhất", gần như luôn là DESC.

Thực hành

  1. Chạy SELECT * FROM customers; rồi SELECT * FROM customers ORDER BY id;. So sánh thứ tự hai kết quả — trong bộ dữ liệu nhỏ này có thể giống nhau, nhưng hãy tập thói quen thêm ORDER BY.
  2. Chạy SELECT id, name, signup_date FROM customers ORDER BY signup_date DESC LIMIT 5; và xác nhận năm khách mới nhất.
  3. Mở bài luyện Lấy toàn bộ khách hàng (select-all-customers) và nộp bài. Yêu cầu là trả về mọi cột của mọi khách hàng, sắp xếp theo id tăng dần. Đáp án chính là truy vấn thứ hai trong mục ví dụ, thêm ORDER BY id.

Nếu bài luyện báo sai, đừng vội sửa mò. Đọc thông báo: nó thường nói bạn thiếu cột, thừa cột hay sai thứ tự. Với bài này, thứ tự dòng quan trọng vì yêu cầu có ORDER BY id.

Lỗi thường gặp

Triệu chứngNguyên nhânCách sửa
syntax error at end of inputQuên FROM hoặc quên dấu ;Kiểm tra lại cấu trúc SELECT ... FROM ...;
Kết quả đúng dữ liệu nhưng bài luyện báo sai thứ tựThiếu ORDER BY idYêu cầu có "sắp xếp theo id" thì phải viết ORDER BY id
SELECT * trả về cột lạ so với tài liệuBảng vừa được thêm cộtKhông phụ thuộc vào *; liệt kê cột bạn cần
Kết quả chỉ có một phần dòngCòn sót LIMIT từ lần thử trướcXoá LIMIT hoặc tăng số dòng
ORDER BY ten báo lỗi không có cộtDùng tên tiếng Việt thay vì tên cột thậtXem tên cột bằng SELECT * ... LIMIT 1

Tóm tắt

  • SELECT chọn cột, FROM chọn bảng; WHERE, ORDER BY, LIMIT là tuỳ chọn nhưng cực kỳ thường dùng.
  • Máy thực thi theo thứ tự FROM → WHERE → SELECT → ORDER BY → LIMIT, khác thứ tự bạn viết.
  • Kết quả truy vấn là một bảng tạm có tên cột và kiểu dữ liệu.
  • Không có ORDER BY thì không có thứ tự đảm bảo.
  • SELECT * để khám phá; liệt kê cột khi truy vấn được dùng thật.

Dùng ← → để chuyển bài