Hàm tổng hợp (aggregate) gộp nhiều dòng thành một giá trị: COUNT, SUM, AVG, MAX, MIN.
Điểm hay bị hỏi nhất là cách xử lý NULL:
- COUNT(*) đếm mọi dòng kể cả NULL; COUNT(col) bỏ qua dòng NULL — nên COUNT(phone) cho biết có bao nhiêu user có số điện thoại.
- SUM/AVG/MAX/MIN đều bỏ qua NULL (không coi NULL là 0).
- COUNT(DISTINCT city) đếm số giá trị không trùng.
Vài hàm nâng cao đáng nhớ (PostgreSQL):
- STRING_AGG / ARRAY_AGG: nối giá trị trong nhóm — STRING_AGG(tag, ', ' ORDER BY tag).
- FILTER: gom có điều kiện trong một query thay vì nhiều subquery (kiểu pivot):
COUNT(*) FILTER (WHERE status = 'active') AS active,
COUNT(*) FILTER (WHERE status = 'inactive') AS inactive- PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary): tính trung vị — ít bị méo bởi giá trị ngoại lai hơn AVG.
Aggregate functions collapse many rows into one value: COUNT, SUM, AVG, MAX, MIN.
The most-asked point is NULL handling:
- COUNT(*) counts every row including NULLs; COUNT(col) skips NULL rows — so COUNT(phone) tells you how many users have a phone number.
- SUM/AVG/MAX/MIN all skip NULLs (they don't treat NULL as 0).
- COUNT(DISTINCT city) counts unique values.
A few advanced ones worth remembering (PostgreSQL):
- STRING_AGG / ARRAY_AGG: concatenate values within a group — STRING_AGG(tag, ', ' ORDER BY tag).
- FILTER: conditional aggregation in one query instead of multiple subqueries (pivot-style):
COUNT(*) FILTER (WHERE status = 'active') AS active,
COUNT(*) FILTER (WHERE status = 'inactive') AS inactive- PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary): computes the median — less skewed by outliers than AVG.