Hướng dẫn

Google Sheets Nâng Cao Bài 4: Hàm QUERY - Lọc và Phân Tích Dữ Liệu Chuyên Nghiệp

Tuân HoangTuân Hoang
15 phút đọc
Google Sheets Nâng Cao Bài 4: Hàm QUERY - Lọc và Phân Tích Dữ Liệu Chuyên Nghiệp

Google Sheets Nâng Cao Bài 4: Hàm QUERY - Lọc và Phân Tích Dữ Liệu Chuyên Nghiệp

Chào mừng bạn đến với Bài 4 trong series Google Sheets Nâng Cao! Sau khi đã nắm vững Data Validation (Bài 1), Conditional Formatting (Bài 2), và IMPORTRANGE (Bài 3), hôm nay chúng ta sẽ khám phá một trong những hàm mạnh mẽ nhất trong Google Sheets: hàm QUERY.

Hàm QUERY cho phép bạn lọc, sắp xếp, nhóm và phân tích dữ liệu bằng cú pháp tương tự SQL — ngôn ngữ truy vấn cơ sở dữ liệu. Sau bài học này, bạn sẽ có thể xây dựng báo cáo tự động mà không cần Pivot Table thủ công hay macro phức tạp.

Tổng Quan Series Google Sheets Nâng Cao

1. Hàm QUERY Là Gì?

QUERY là hàm cho phép bạn truy vấn dữ liệu trong Google Sheets bằng ngôn ngữ Google Visualization API Query Language — một biến thể đơn giản hóa của SQL. Thay vì dùng nhiều hàm lồng nhau (IF + VLOOKUP + SUMIF...), một công thức QUERY duy nhất có thể thay thế tất cả.

Cú Pháp Cơ Bản

=QUERY(data, query, [headers])

// Trong đó:
// data    = Phạm vi dữ liệu (VD: A1:G100 hoặc 'Sheet2'!A:G)
// query   = Câu truy vấn dạng text (VD: "SELECT A, B WHERE C > 100")
// headers = Số hàng tiêu đề (mặc định: -1 = tự nhận diện)

// Ví dụ đơn giản nhất:
=QUERY(A1:D100, "SELECT A, B, C WHERE D > 1000000", 1)

Tại Sao Dùng QUERY Thay Vì VLOOKUP/FILTER?

Tình Huống Hàm Cũ QUERY
Lọc theo nhiều điều kiện FILTER phức tạp WHERE A="x" AND B>100
Tổng theo nhóm SUMIF từng nhóm GROUP BY + SUM
Sắp xếp kết quả SORT + FILTER ORDER BY
Lấy n hàng đầu SMALL/LARGE phức tạp LIMIT 10
Đổi tên cột Không thể LABEL A 'Tên Mới'

2. Mệnh Đề SELECT - Chọn Cột

SELECT là mệnh đề đầu tiên và bắt buộc, xác định cột nào sẽ xuất hiện trong kết quả:

// Chọn tất cả cột:
=QUERY(A1:F100, "SELECT *", 1)

// Chọn cột cụ thể (theo ký tự cột):
=QUERY(A1:F100, "SELECT A, C, E", 1)

// Chọn theo vị trí cột (Col1, Col2...):
=QUERY(A1:F100, "SELECT Col1, Col3, Col5", 1)

// Thứ tự cột trong kết quả có thể khác thứ tự gốc:
=QUERY(A1:F100, "SELECT F, A, C", 1) // F trước, rồi A, rồi C

// Bảng dữ liệu bán hàng: A=Ngày, B=Sản phẩm, C=KV, D=Số lượng, E=Đơn giá, F=Doanh thu
// Lấy ngày, sản phẩm và doanh thu:
=QUERY(A1:F1000, "SELECT A, B, F", 1)

3. Mệnh Đề WHERE - Lọc Dữ Liệu

WHERE lọc các hàng thỏa mãn điều kiện. Đây là mệnh đề bạn sẽ dùng nhiều nhất:

3.1 Điều Kiện Cơ Bản

// So sánh số:
=QUERY(A1:F1000, "SELECT A, B, F WHERE F > 5000000", 1)
=QUERY(A1:F1000, "SELECT A, B, F WHERE D >= 10 AND D <= 50", 1)

// So sánh text (phân biệt hoa thường):
=QUERY(A1:F1000, "SELECT A, B, F WHERE B = 'iPhone 15'", 1)

// Text chứa chuỗi (CONTAINS tương đương LIKE '%...%' trong SQL):
=QUERY(A1:F1000, "SELECT A, B WHERE B CONTAINS 'Samsung'", 1)

// Text bắt đầu bằng (STARTS WITH):
=QUERY(A1:F1000, "SELECT A, B WHERE B STARTS WITH 'Máy'", 1)

// Text kết thúc bằng (ENDS WITH):
=QUERY(A1:F1000, "SELECT A, B WHERE B ENDS WITH 'Pro'", 1)

// So sánh ngày (phải dùng hàm date()):
=QUERY(A1:F1000, "SELECT A, B, F WHERE A >= date '2027-01-01'", 1)
=QUERY(A1:F1000, "SELECT A, B, F WHERE A >= date '2027-01-01' AND A <= date '2027-01-31'", 1)

3.2 Điều Kiện Kết Hợp AND/OR

// AND - cả hai điều kiện đều phải đúng:
=QUERY(A1:F1000,
  "SELECT A, B, C, F
   WHERE C = 'Hà Nội' AND F > 10000000",
  1
)

// OR - ít nhất một điều kiện đúng:
=QUERY(A1:F1000,
  "SELECT A, B, C, F
   WHERE C = 'Hà Nội' OR C = 'TP HCM'",
  1
)

// Kết hợp AND và OR (dùng ngoặc):
=QUERY(A1:F1000,
  "SELECT A, B, C, F
   WHERE (C = 'Hà Nội' OR C = 'TP HCM') AND F > 5000000",
  1
)

// NOT - phủ định điều kiện:
=QUERY(A1:F1000,
  "SELECT A, B, C, F
   WHERE NOT C = 'Hà Nội'",
  1
)

// IS NULL / IS NOT NULL - kiểm tra ô trống:
=QUERY(A1:F1000, "SELECT A, B WHERE C IS NOT NULL", 1)

3.3 Sử Dụng Biến Từ Ô Khác Trong WHERE

// Kết hợp giá trị ô vào câu query (dùng &):
// Ô H1 chứa tên khu vực người dùng chọn: "Hà Nội"
=QUERY(A1:F1000,
  "SELECT A, B, F WHERE C = '"&H1&"'",
  1
)

// Ô H2 chứa ngưỡng doanh thu: 10000000
=QUERY(A1:F1000,
  "SELECT A, B, F WHERE F > "&H2&"",
  1
)

// Kết hợp cả text và số:
=QUERY(A1:F1000,
  "SELECT A, B, F WHERE C = '"&H1&"' AND F > "&H2,
  1
)

// Với ngày tháng (cần format đặc biệt):
// Ô H3 chứa ngày: 01/01/2027
=QUERY(A1:F1000,
  "SELECT A, B, F WHERE A >= date '"&TEXT(H3,"yyyy-mm-dd")&"'",
  1
)

4. Mệnh Đề ORDER BY - Sắp Xếp

// Sắp xếp tăng dần (mặc định ASC):
=QUERY(A1:F1000, "SELECT A, B, F ORDER BY F", 1)
=QUERY(A1:F1000, "SELECT A, B, F ORDER BY F ASC", 1)

// Sắp xếp giảm dần:
=QUERY(A1:F1000, "SELECT A, B, F ORDER BY F DESC", 1)

// Sắp xếp theo nhiều cột:
=QUERY(A1:F1000, "SELECT A, B, C, F ORDER BY C ASC, F DESC", 1)

// Ứng dụng: Top 10 sản phẩm bán chạy nhất
=QUERY(A1:F1000,
  "SELECT B, SUM(D), SUM(F)
   GROUP BY B
   ORDER BY SUM(F) DESC
   LIMIT 10
   LABEL B 'Sản Phẩm', SUM(D) 'Tổng SL', SUM(F) 'Tổng Doanh Thu'",
  1
)

5. Mệnh Đề LIMIT - Giới Hạn Kết Quả

// Lấy 10 hàng đầu tiên:
=QUERY(A1:F1000, "SELECT A, B, F LIMIT 10", 1)

// Bỏ qua 5 hàng đầu, lấy 10 hàng tiếp theo (OFFSET):
=QUERY(A1:F1000, "SELECT A, B, F LIMIT 10 OFFSET 5", 1)

// Top 5 giao dịch lớn nhất:
=QUERY(A1:F1000,
  "SELECT A, B, F
   ORDER BY F DESC
   LIMIT 5",
  1
)

// Giao dịch lớn nhất gần nhất (sắp xếp theo ngày giảm dần, lấy 1):
=QUERY(A1:F1000,
  "SELECT A, B, F
   WHERE F = MAX(F)
   LIMIT 1",
  1
)

6. Mệnh Đề GROUP BY - Nhóm Dữ Liệu

GROUP BY là mệnh đề giúp bạn tổng hợp dữ liệu theo nhóm — tương tự Pivot Table nhưng tự động cập nhật:

6.1 Hàm Aggregate Trong QUERY

Hàm Ý Nghĩa Ví Dụ
SUMTổngSUM(F)
COUNTĐếm tất cả (kể cả null)COUNT(A)
COUNTAĐếm ô không trốngCOUNTA(B)
AVGTrung bìnhAVG(E)
MAXGiá trị lớn nhấtMAX(F)
MINGiá trị nhỏ nhấtMIN(F)

6.2 GROUP BY Cơ Bản

// Doanh thu theo sản phẩm:
=QUERY(A1:F1000,
  "SELECT B, SUM(F)
   WHERE A IS NOT NULL
   GROUP BY B
   ORDER BY SUM(F) DESC
   LABEL B 'Sản Phẩm', SUM(F) 'Tổng Doanh Thu'",
  1
)

// Số đơn hàng và doanh thu theo khu vực:
=QUERY(A1:F1000,
  "SELECT C, COUNT(A), SUM(F), AVG(F)
   GROUP BY C
   ORDER BY SUM(F) DESC
   LABEL C 'Khu Vực', COUNT(A) 'Số ĐH', SUM(F) 'Tổng DT', AVG(F) 'DT TB'",
  1
)

// Group theo nhiều cột (theo sản phẩm + khu vực):
=QUERY(A1:F1000,
  "SELECT B, C, SUM(D), SUM(F)
   GROUP BY B, C
   ORDER BY B, SUM(F) DESC
   LABEL B 'Sản Phẩm', C 'Khu Vực', SUM(D) 'Tổng SL', SUM(F) 'Tổng DT'",
  1
)

6.3 Mệnh Đề HAVING - Lọc Sau Khi GROUP BY

// HAVING giống WHERE nhưng áp dụng SAU khi đã GROUP BY
// Lọc chỉ sản phẩm có doanh thu > 100 triệu:
=QUERY(A1:F1000,
  "SELECT B, SUM(F)
   GROUP BY B
   HAVING SUM(F) > 100000000
   ORDER BY SUM(F) DESC",
  1
)

// Khu vực có hơn 50 đơn hàng:
=QUERY(A1:F1000,
  "SELECT C, COUNT(A), SUM(F)
   GROUP BY C
   HAVING COUNT(A) > 50",
  1
)

7. Mệnh Đề LABEL - Đặt Tên Cột

// Đặt tên cho cột aggregate:
=QUERY(A1:F1000,
  "SELECT B, SUM(D), SUM(F)
   GROUP BY B
   LABEL SUM(D) 'Tổng Số Lượng', SUM(F) 'Tổng Doanh Thu'",
  1
)

// Đặt tên cho tất cả cột:
=QUERY(A1:F1000,
  "SELECT A, B, C, F
   LABEL A 'Ngày Bán', B 'Sản Phẩm', C 'Khu Vực', F 'Doanh Thu'",
  1
)

// Đặt tên trống để ẩn tên cột:
=QUERY(A1:F1000,
  "SELECT A, B, F
   LABEL A '', B '', F ''",
  1
)

8. QUERY Kết Hợp IMPORTRANGE

Đây là combo cực kỳ mạnh mẽ — bạn có thể lọc dữ liệu từ file Google Sheets khác:

// Cú pháp kết hợp:
=QUERY(
  IMPORTRANGE("URL_FILE_KHAC", "Sheet1!A:F"),
  "SELECT Col1, Col2, Col6 WHERE Col3 = 'Hà Nội'",
  1
)

// Lấy dữ liệu bán hàng từ file tổng, lọc theo khu vực:
=QUERY(
  IMPORTRANGE("https://docs.google.com/spreadsheets/d/1abc.../edit", "Data!A:F"),
  "SELECT Col1, Col2, Col3, Col6
   WHERE Col3 = '"&B1&"'
   AND Col1 >= date '"&TEXT(C1,"yyyy-mm-dd")&"'
   ORDER BY Col1 DESC",
  1
)

// Lưu ý: Lần đầu chạy cần "Allow access" để kết nối 2 file
// Kết hợp IMPORTRANGE + QUERY chậm hơn nếu dữ liệu lớn
// Giải pháp: Import vào sheet trung gian, QUERY từ sheet đó

9. Xây Dựng Báo Cáo Bán Hàng Tự Động Với QUERY

Phần này là ứng dụng thực tế nhất — xây dựng dashboard báo cáo hoàn chỉnh chỉ với QUERY:

9.1 Báo Cáo Doanh Thu Theo Tháng

// Giả sử cột A = Ngày bán, F = Doanh thu

// Doanh thu tháng 1/2027:
=QUERY(A2:F1000,
  "SELECT SUM(F) WHERE A >= date '2027-01-01' AND A <= date '2027-01-31'",
  0
)

// Doanh thu theo từng tháng trong năm 2027:
=QUERY(A2:F1000,
  "SELECT MONTH(A)+1, SUM(F)
   WHERE YEAR(A) = 2027
   GROUP BY MONTH(A)
   ORDER BY MONTH(A)
   LABEL MONTH(A)+1 'Tháng', SUM(F) 'Doanh Thu'",
  0
)

// Lưu ý: MONTH(A) trả về 0-11, nên cộng thêm 1 để ra 1-12

9.2 Báo Cáo Theo Sản Phẩm x Khu Vực (Cross-tab)

// Top sản phẩm theo từng khu vực:
=QUERY(A2:F1000,
  "SELECT B, C, SUM(F)
   GROUP BY B, C
   ORDER BY B, SUM(F) DESC
   LABEL B 'Sản Phẩm', C 'Khu Vực', SUM(F) 'Doanh Thu'",
  0
)

// Chỉ lấy top 3 sản phẩm mỗi khu vực (cần trick với RANK):
// Cách dễ nhất: tạo helper column với RANK, rồi QUERY WHERE rank <= 3

9.3 Báo Cáo So Sánh Cùng Kỳ (YoY)

// Doanh thu theo tháng 2026 vs 2027:
// Sheet 1: QUERY năm 2026
=QUERY(A2:F1000,
  "SELECT MONTH(A)+1, SUM(F) WHERE YEAR(A)=2026 GROUP BY MONTH(A)",
  0
)

// Sheet 2: QUERY năm 2027
=QUERY(A2:F1000,
  "SELECT MONTH(A)+1, SUM(F) WHERE YEAR(A)=2027 GROUP BY MONTH(A)",
  0
)

// Kết hợp 2 QUERY với ARRAY và so sánh:
// Cột D = Tăng trưởng: =(Năm2027-Năm2026)/Năm2026

9.4 Dashboard Bán Hàng Hoàn Chỉnh

// ===== KPI CARDS =====

// Tổng doanh thu tháng hiện tại:
=QUERY(Data!A2:F5000,
  "SELECT SUM(F) WHERE YEAR(A)="&YEAR(TODAY())&" AND MONTH(A)+1="&MONTH(TODAY()),
  0
)

// Số đơn hàng hôm nay:
=COUNTIF(Data!A2:A5000, TODAY())

// Top sản phẩm tuần này:
=QUERY(Data!A2:F5000,
  "SELECT B, SUM(F)
   WHERE A >= date '"&TEXT(TODAY()-WEEKDAY(TODAY(),2)+1,"yyyy-mm-dd")&"'
   GROUP BY B ORDER BY SUM(F) DESC LIMIT 5
   LABEL B 'Sản Phẩm', SUM(F) 'Doanh Thu'",
  0
)

// ===== BẢNG CHI TIẾT =====

// 20 giao dịch gần nhất:
=QUERY(Data!A2:F5000,
  "SELECT A, B, C, D, E, F
   ORDER BY A DESC
   LIMIT 20
   LABEL A 'Ngày', B 'SP', C 'KV', D 'SL', E 'Đơn giá', F 'Tổng'",
  0
)

10. QUERY Nâng Cao - Các Kỹ Thuật Ít Người Biết

10.1 QUERY Với Scalar Functions

// Hàm ngày tháng trong QUERY:
// YEAR(A), MONTH(A), DAY(A), HOUR(A), MINUTE(A), SECOND(A)
// DATE(year, month, day)

// Nhóm theo năm:
=QUERY(A2:F1000,
  "SELECT YEAR(A), SUM(F) GROUP BY YEAR(A) LABEL YEAR(A) 'Năm'",
  0
)

// Nhóm theo quý:
=QUERY(A2:F1000,
  "SELECT YEAR(A), QUARTER(A), SUM(F)
   GROUP BY YEAR(A), QUARTER(A)
   LABEL YEAR(A) 'Năm', QUARTER(A) 'Quý', SUM(F) 'Doanh Thu'",
  0
)

// Hàm toán học:
// ROUND(F, 0), ABS(F)
=QUERY(A2:F1000,
  "SELECT B, ROUND(AVG(F), 0) GROUP BY B LABEL ROUND(AVG(F),0) 'DT TB'",
  0
)

10.2 QUERY Lồng Nhau (Subquery)

// QUERY không hỗ trợ subquery trực tiếp
// Nhưng bạn có thể dùng QUERY bên trong QUERY qua array:

=QUERY(
  QUERY(A2:F1000,
    "SELECT B, SUM(F) GROUP BY B",
    0
  ),
  "SELECT Col1, Col2 WHERE Col2 > 50000000",
  0
)

// Hoặc dùng FILTER + QUERY:
=QUERY(
  FILTER(A2:F1000, F2:F1000 > 1000000),
  "SELECT Col2, SUM(Col6) GROUP BY Col2",
  0
)

10.3 QUERY Với Format

// FORMAT để định dạng số và ngày trong kết quả:
=QUERY(A2:F1000,
  "SELECT A, B, F
   FORMAT A 'dd/MM/yyyy', F '#,##0 ₫'",
  1
)

// Định dạng % cho tỷ lệ:
=QUERY(A2:F1000,
  "SELECT B, SUM(F)/1000000
   GROUP BY B
   FORMAT SUM(F)/1000000 '#,##0.0'
   LABEL SUM(F)/1000000 'Doanh Thu (triệu)'",
  1
)

11. Xử Lý Lỗi Thường Gặp Với QUERY

Lỗi #VALUE! - Sai Kiểu Dữ Liệu

// Nguyên nhân: Cột chứa cả số và text, hoặc ngày bị format sai
// Giải pháp: Kiểm tra Data Type của cột, đảm bảo nhất quán
// Debug: =ISNUMBER(A2), =ISTEXT(A2), =ISDATE(A2)

Lỗi "Unable to parse query string"

// Nguyên nhân: Sai cú pháp query (thiếu nháy đơn, sai tên mệnh đề...)
// Kiểm tra: Xem lại cú pháp, đặc biệt là nháy đơn trong text
// Sai:  "SELECT A WHERE B = "Hà Nội""  (dùng nháy đôi cho text)
// Đúng: "SELECT A WHERE B = 'Hà Nội'"  (phải dùng nháy đơn)

Lỗi Khi Kết Hợp Biến Số và Text

// Sai: "SELECT A WHERE F > '50000'"  (số không dùng nháy đơn)
// Đúng: "SELECT A WHERE F > 50000"

// Sai: "SELECT A WHERE B = "&H1&""   (thiếu nháy đơn bao quanh text)
// Đúng: "SELECT A WHERE B = '"&H1&"'"

QUERY Trả Về Ít Dòng Hơn Mong Đợi

// Kiểm tra: Có thể có dòng trống trong dữ liệu gốc
// Giải pháp: Thêm WHERE A IS NOT NULL để bỏ qua dòng trống
=QUERY(A1:F1000,
  "SELECT A, B, F WHERE A IS NOT NULL ORDER BY A DESC",
  1
)

12. Bài Tập Thực Hành

Để nắm vững QUERY, hãy thực hành với bộ dữ liệu bán hàng mẫu:

Bài Tập 1 - Cơ Bản

// Yêu cầu: Lọc tất cả đơn hàng tháng 3/2027, khu vực TP HCM, có doanh thu > 2 triệu
// Kết quả: Hiển thị ngày, tên sản phẩm, số lượng, doanh thu

=QUERY(A2:F1000,
  "SELECT A, B, D, F
   WHERE A >= date '2027-03-01'
     AND A <= date '2027-03-31'
     AND C = 'TP HCM'
     AND F > 2000000
   ORDER BY F DESC",
  1
)

Bài Tập 2 - Nhóm Dữ Liệu

// Yêu cầu: Bảng tổng hợp doanh thu theo tháng x khu vực cho năm 2027
// Kết quả: Tháng, Hà Nội, TP HCM, Đà Nẵng, Tổng

// Cách: Tạo 4 QUERY riêng (1 cho mỗi khu vực + 1 tổng), đặt cạnh nhau
// Hoặc dùng QUERY nhóm theo tháng + khu vực, rồi dùng pivot thủ công

Bài Tập 3 - Dashboard Tự Động

// Yêu cầu: Tạo sheet Dashboard với:
// - Ô B1: Chọn khu vực (dropdown)
// - Ô B2: Chọn tháng (dropdown 1-12)
// - Bảng kết quả: Top 10 sản phẩm của khu vực + tháng đã chọn

=QUERY(Data!A2:F5000,
  "SELECT B, SUM(D), SUM(F)
   WHERE C = '"&B1&"'
     AND MONTH(A)+1 = "&B2&"
     AND YEAR(A) = 2027
   GROUP BY B
   ORDER BY SUM(F) DESC
   LIMIT 10
   LABEL B 'Sản Phẩm', SUM(D) 'Tổng SL', SUM(F) 'Tổng DT'",
  0
)

Tổng Kết Bài 4

Hàm QUERY là một trong những công cụ mạnh nhất trong Google Sheets, cho phép bạn:

  • Lọc dữ liệu với SELECT + WHERE đa điều kiện (AND/OR/NOT)
  • Sắp xếp kết quả với ORDER BY (ASC/DESC)
  • Giới hạn kết quả với LIMIT + OFFSET
  • Tổng hợp dữ liệu với GROUP BY + SUM/COUNT/AVG/MAX/MIN
  • Lọc sau nhóm với HAVING
  • Đặt tên cột với LABEL
  • Định dạng đầu ra với FORMAT
  • Kết hợp với IMPORTRANGE để truy vấn dữ liệu từ file khác
  • Nhúng biến từ ô khác vào câu query bằng toán tử &

Bài 5 tiếp theo, chúng ta sẽ học về Google Apps Script cơ bản — cách tự động hóa các tác vụ lặp đi lặp lại trong Google Sheets mà không cần biết lập trình chuyên sâu.

Xem thêm các bài viết liên quan:

Chia sẻ bài viết:

Tuân Hoang

Tuân Hoang

Đội ngũ SheetStore

Bạn thấy bài viết hữu ích?

Đăng ký nhận thông báo khi có bài viết mới.

Nhận thông báo khi có bài viết mới. Không spam, hứa luôn! 😊

Bình luận (0)

Vui lòng đăng nhập để tham gia thảo luận