aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL AVG gặp NULL: dữ liệu chưa có không tự trở thành số 0

Suong Nguyen by Suong Nguyen
03/11/2026
in Backend
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Một nhóm có điểm 10, điểm 20 và một bản ghi chưa chấm. Trung bình của các điểm đã biết khác với trung bình sau khi coi bản chưa chấm là 0. Cả hai truy vấn đều chạy được, nhưng chúng biểu diễn hai quy tắc báo cáo khác nhau.

Bài đối chiếu PostgreSQL 17 và SQLite ngày 03/11/2026. SQL được chạy với Python 3.9.6, SQLite 3.54.0 trong database bộ nhớ; chưa chạy PostgreSQL server hoặc benchmark. Dữ liệu chỉ minh họa điểm đánh giá, không phải quy tắc tính điểm bắt buộc cho mọi sản phẩm.

Tạo ba nhóm có dữ liệu khác nhau

Chạy fixture trên database thử trống:

CREATE TABLE demo_scores (
    id INTEGER PRIMARY KEY,
    team TEXT NOT NULL,
    score INTEGER
);
INSERT INTO demo_scores VALUES
    (1, 'A', 10),
    (2, 'A', 20),
    (3, 'A', NULL),
    (4, 'B', NULL),
    (5, 'C', 0);

Nhóm A có ba hàng nhưng chỉ hai điểm đã biết. B có một hàng chưa chấm. C có điểm thật bằng 0. Phân biệt B với C là phần quan trọng của bài, vì việc cùng hiển thị một số 0 trên dashboard có thể che mất trạng thái thu thập dữ liệu.

Đọc trung bình cùng số lượng quan sát

SELECT team,
       COUNT(*) AS rows_seen,
       COUNT(score) AS scores_known,
       AVG(score) AS average_known,
       AVG(COALESCE(score, 0)) AS average_with_zero,
       COALESCE(AVG(score), 0) AS display_fallback
FROM demo_scores
GROUP BY team
ORDER BY team;

Kết quả đã kiểm tra với SQLite:

  • A có 3 hàng, 2 điểm; ba cột trung bình lần lượt là 15, 10 và 15.
  • B có 1 hàng, 0 điểm; ba cột lần lượt là NULL, 0 và 0.
  • C có 1 hàng, 1 điểm; ba cột đều bằng 0.

AVG(score) dùng các giá trị không NULL. AVG(COALESCE(score, 0)) thay dữ liệu từng hàng trước khi gom nhóm, nên bản chưa chấm góp một điểm 0 vào mẫu số. COALESCE(AVG(score), 0) chỉ thay kết quả cuối khi trung bình là NULL; nó không đưa hàng thiếu điểm vào trung bình của nhóm A.

Vì vậy, vị trí COALESCE là một quyết định nghiệp vụ. Với báo cáo “điểm trung bình của những lượt đã chấm”, cột average_known cùng scores_known giúp nói rõ căn cứ. Nếu sản phẩm thật sự quy định lượt chưa chấm tính 0, hãy ghi quy tắc đó và dùng công thức tương ứng.

Tập rỗng khác với một nhóm có mặt

Chạy thêm hai truy vấn:

SELECT COUNT(*) AS rows_seen, AVG(score) AS average_known,
       COALESCE(AVG(score), 0) AS display_fallback
FROM demo_scores
WHERE team = 'D';

SELECT team, COALESCE(AVG(score), 0) AS display_fallback
FROM demo_scores
WHERE team = 'D'
GROUP BY team;

Truy vấn đầu đã được kiểm tra trả một hàng (0, NULL, 0). Truy vấn có GROUP BY trả không có hàng nào. COALESCE thay một giá trị NULL đã được tạo, không tự sinh một nhóm D chưa có trong đầu vào.

Nếu báo cáo phải luôn có đủ các nhóm, cần một nguồn danh sách nhóm và thiết kế truy vấn kết hợp phù hợp. Đừng chỉ thêm COALESCE rồi cho rằng mọi nhóm thiếu sẽ xuất hiện. Fixture này chưa triển khai truy vấn danh mục nhóm đầy đủ.

Cách kiểm tra trước khi triển khai

Giữ test cho nhóm có đủ điểm, thiếu một phần, toàn NULL, điểm 0 thật và không có hàng. Kiểm tra response API có phân biệt NULL với số 0 hay không; frontend không nên tự quyết định thay mọi giá trị thiếu bằng 0 nếu backend chưa định nghĩa ý nghĩa.

SQLite có quy tắc riêng với text không giống số trong AVG. Bài chỉ dùng cột có giá trị integer hoặc NULL, nên không chứng minh dữ liệu text bẩn được xử lý đúng. Với PostgreSQL, kiểu trả về cũng phụ thuộc kiểu đầu vào; driver có thể biểu diễn numeric khác float của SQLite.

Chốt ý nghĩa dữ liệu thiếu trước, rồi mới chọn vị trí COALESCE. Báo cáo dễ hiểu khi người đọc biết số nào là kết quả tính từ quan sát thật và số nào chỉ là fallback để hiển thị.

Nguồn tham khảo

  • PostgreSQL 17: AVG và aggregate functions
  • PostgreSQL 17: COALESCE
  • SQLite: AVG, COUNT và dữ liệu NULL

Tags: Báo cáoDatabaseSQL
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQL EXISTS: lọc khách có đơn mà không nhân dòng khách hàng

by Suong Nguyen
02/11/2026
0

So sánh JOIN với EXISTS trên fixture có nhiều đơn cho một khách để giữ đúng đơn vị một dòng trong danh sách trả về.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Lọc thời gian trong SQL: dùng khoảng nửa mở để không trùng biên

by Suong Nguyen
01/11/2026
0

So sánh BETWEEN với điều kiện >= đầu kỳ và < đầu kỳ kế tiếp bằng fixture ở đúng ranh giới tháng.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

SQLite: có FOREIGN KEY nhưng vẫn lọt dữ liệu mồ côi?

by Suong Nguyen
31/10/2026
0

Bật và đọc lại PRAGMA foreign_keys trên từng connection SQLite, rồi thử cả insert sai lẫn kiểm tra dữ liệu đã tồn tại.

Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

UNIQUE và NULL trong PostgreSQL: chốt quy tắc cho khóa tùy chọn

by Suong Nguyen
30/10/2026
0

Phân biệt cột tùy chọn có UNIQUE, UNIQUE NULLS NOT DISTINCT và NOT NULL UNIQUE trước khi viết migration.

Next Post
Minh họa kiến trúc backend API gọn gàng cho sản phẩm nhỏ

Array.some và every: chọn đúng câu hỏi, nhớ trường hợp mảng rỗng

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native Text: rút gọn hai dòng và vẫn có đường đọc đầy đủ
  • Vì sao map(parseInt) biến index thành radix?
  • Android INVISIBLE và GONE: ẩn nội dung có cần giữ chỗ không?

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply