Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

JQL Mastery và Dashboards

Jira and Agile Tools Mastery Bài 2/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là một Project Manager đang quản lý một backlog có 800 issue trải trên 4 team. Sếp nhắn Slack lúc 4 giờ chiều: "Cho anh biết ngay có bao nhiêu Story chưa ai đụng tới trong 2 tuần qua, và bao nhiêu bug nghiêm trọng đang bị treo?" Nếu bạn phải mở từng board, kéo từng cột, lọc bằng mắt rồi đếm tay, thì đến 6 giờ tối bạn vẫn chưa có câu trả lời — mà câu trả lời đó, một người thạo JQL chỉ mất 30 giây để có.

JQL — viết tắt của Jira Query Language — là ngôn ngữ truy vấn giúp bạn "hỏi" Jira bất cứ điều gì về dữ liệu công việc, thay vì phụ thuộc vào các bộ lọc bấm chuột có sẵn. Nó là điểm khác biệt lớn nhất giữa một PM chỉ biết dùng Jira ở mức cơ bản và một PM thực sự làm chủ công cụ. Khi bạn kết hợp JQL với Dashboard — bảng điều khiển trực quan hiển thị các con số quan trọng theo thời gian thực — bạn biến Jira từ một nơi lưu trữ task thành một hệ thống ra quyết định.

Trong bài này, chúng ta không dừng ở cú pháp cơ bản. Bài 8 và Bài 9 trong khóa sẽ đi sâu vào nền tảng và JQL nâng cao cho PM. Ở Bài 2 này, mục tiêu của chúng ta là thành thạo những power query có giá trị cao nhất trong công việc hằng ngàybiến chúng thành Dashboard sống động để cả team và cấp trên đều nhìn thấy. Nói cách khác: bạn học cách đặt câu hỏi thông minh, rồi trưng bày câu trả lời một cách chuyên nghiệp.

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

JQL hoạt động như thế nào

Một câu JQL được cấu thành từ ba thành phần: field (trường dữ liệu, ví dụ status, assignee, priority), operator (toán tử so sánh, ví dụ =, !=, >, IN, ~), và value (giá trị bạn muốn so sánh). Ghép lại thành một mệnh đề, ví dụ:

status = "In Progress"

Câu này trả về tất cả issue đang ở trạng thái "In Progress". Bạn nối nhiều mệnh đề bằng toán tử logic AND, OR, NOT:

project = MOBILE AND status = "In Progress" AND assignee = currentUser()

Điểm mạnh của JQL nằm ở ba nhóm tính năng mà giao diện bấm chuột không có:

1. Hàm thời gian tương đối. Bạn không phải nhập ngày cụ thể. -14d nghĩa là "14 ngày trước tính từ hôm nay", startOfWeek() là đầu tuần, endOfMonth() là cuối tháng. Nhờ đó câu query luôn "sống" — hôm nay chạy ra kết quả của hôm nay, tuần sau chạy ra kết quả của tuần sau, không cần sửa.

2. Hàm động về người và sprint. currentUser() tự hiểu là người đang đăng nhập, openSprints() là mọi sprint đang mở, membersOf("team-mobile") là tất cả thành viên trong một group. Điều này cho phép bạn tạo một filter dùng chung cho cả team mà mỗi người mở lên vẫn thấy đúng phần của mình.

3. Toán tử WAS, CHANGED, IN. Đây là "vũ khí bí mật". WASCHANGED truy vấn vào lịch sử thay đổi của issue, không chỉ trạng thái hiện tại. Ví dụ "issue nào từng bị đưa ra khỏi sprint" — chỉ JQL với CHANGED mới trả lời được.

Power Queries — những câu hỏi đắt giá nhất

Dưới đây là bộ query mà một PM nên thuộc lòng. Tôi gọi chúng là "power query" vì mỗi câu trả lời một câu hỏi quản trị thật sự.

Việc bị bỏ quên (stale items) — không cập nhật trong 14 ngày:

updated <= -14d AND status != Done AND type = Story

Đây là câu quét ra những Story đang "chết lâm sàng": chưa xong nhưng cũng không ai động tới suốt hai tuần. Đó thường là dấu hiệu của task bị block ngầm, hoặc scope không rõ ràng.

Thay đổi phạm vi sprint (sprint scope change) — issue được thêm vào giữa chừng:

sprint IN openSprints() AND created >= startOfDay("-9d")

Nếu sprint dài 2 tuần và bạn thấy nhiều issue được tạo mới sau ngày planning, đó là scope creep — phạm vi phình ra ngoài cam kết ban đầu.

Issue từng bị đưa ra khỏi sprint (dùng lịch sử):

issueFunction in removedAfterSprintStart("BOARD", "Sprint 24")

(Cần cài add-on ScriptRunner cho issueFunction; nếu không có, bạn dùng sprint CHANGED trên Jira Cloud để tiệm cận.)

Bug nghiêm trọng đang mở:

type = Bug AND priority IN (Highest, High) AND status != Done ORDER BY priority DESC, created ASC

Việc của tôi cần làm tuần này:

assignee = currentUser() AND sprint IN openSprints() AND status != Done ORDER BY priority DESC

Việc sắp trễ hạn:

duedate <= 3d AND status != Done AND assignee IS NOT EMPTY

Dashboard và Gadget

Một câu JQL trả về một danh sách. Nhưng khi bạn muốn theo dõi liên tục một con số, bạn lưu câu query đó thành Saved Filter (bộ lọc đã lưu), rồi đưa nó vào Dashboard qua các Gadget.

Gadget là các "ô hiển thị" trên dashboard. Bốn gadget quan trọng nhất với PM:

  • Filter Results: hiển thị danh sách issue của một filter — dùng để theo dõi danh sách stale items, bug đang mở.
  • Pie Chart (biểu đồ tròn): chia issue theo một trường, ví dụ theo assignee hoặc priority — thấy ngay ai đang gánh nhiều việc.
  • Two Dimensional Filter Statistics: bảng chéo hai chiều, ví dụ hàng là assignee, cột là status — bức tranh phân bổ công việc toàn team trong một cái nhìn.
  • Created vs Resolved Chart: so sánh số issue tạo mới và số issue đóng theo thời gian — nếu đường "created" luôn cao hơn "resolved", team của bạn đang đuối.
Nguyên tắc vàng: Dashboard được xây trên nền các Saved Filter. Cho nên chất lượng dashboard của bạn phụ thuộc trực tiếp vào chất lượng JQL của bạn. Một câu query cẩu thả sẽ cho ra một biểu đồ đánh lừa người xem.

Tình huống thực tế

Ví dụ 1 — Tiki và cuộc họp thứ Hai không còn "mò kim đáy bể"

Một team phát triển tính năng thanh toán tại một công ty thương mại điện tử lớn ở TP.HCM (bối cảnh tương tự Tiki) có 6 kỹ sư và khoảng 120 issue mở tại mọi thời điểm. Trước đây, mỗi sáng thứ Hai, chị PM tên Ngọc mất gần 45 phút chuẩn bị: mở board, chụp màn hình, đếm tay số việc dở dang, dán vào slide.

Chị Ngọc xây một dashboard gồm bốn gadget dựa trên bốn saved filter:

// Filter 1: Việc quá hạn của team
project = PAY AND duedate < now() AND status != Done

// Filter 2: Việc bị bỏ quên 10 ngày project = PAY AND updated <= -10d AND status IN ("In Progress", "In Review")

// Filter 3: Phân bổ theo người project = PAY AND sprint IN openSprints() AND status != Done

Filter 3 được đưa vào gadget Pie Chart nhóm theo assignee. Kết quả tuần đầu tiên đã lộ ra một sự thật: một bạn kỹ sư đang ôm 28 issue mở, trong khi một bạn khác chỉ có 6. Việc này trước đó không ai nhận ra vì nó bị phân tán trên board. Bài học: JQL và dashboard không chỉ tiết kiệm thời gian, nó phơi bày những mất cân bằng mà mắt thường bỏ sót. Sau khi tái phân bổ, thời gian chuẩn bị họp của chị Ngọc giảm từ 45 phút xuống còn 5 phút — chỉ cần mở dashboard và trình bày.

Ví dụ 2 — Startup fintech ở Singapore và câu chuyện scope creep

Một startup fintech giai đoạn Series A ở Singapore chạy sprint 2 tuần. Sếp engineering phàn nàn rằng team "làm hoài không hết việc" dù velocity trên giấy tờ ổn định. Anh Minh, PM của team, nghi ngờ có scope creep nhưng không có bằng chứng.

Anh dùng power query để đo lượng việc được nhét thêm vào sau ngày planning:

sprint IN openSprints() AND created >= startOfDay("-9d") AND type IN (Story, Bug)

Kết quả: trong một sprint 2 tuần, có 17 issue được tạo mới sau ngày planning, chiếm gần 40% khối lượng sprint. Team không phải làm chậm — họ đang bị dồn thêm việc liên tục mà không ai cắt bớt cam kết ban đầu.

Anh Minh biến câu query này thành một gadget Created vs Resolved trên dashboard, chiếu lên trong buổi retro. Khi con số hiển thị rõ ràng, cuộc tranh luận chuyển từ "team chậm hay không" sang "chúng ta cần một quy trình duyệt việc thêm giữa sprint". Bài học: một con số được đo bằng JQL và trưng bày trên dashboard có sức thuyết phục gấp nhiều lần một lời cảm nhận. Dữ liệu chấm dứt tranh cãi.

Ví dụ 3 — Agency phần mềm ở Đà Nẵng và bộ lọc dùng chung cho nhiều khách hàng

Một agency gia công phần mềm ở Đà Nẵng quản lý 5 dự án cho 5 khách hàng khác nhau trên cùng một instance Jira. PM tên Hà cần mỗi trưởng nhóm chỉ thấy phần việc của mình mà không phải tạo 5 filter riêng.

Chị dùng hàm động để một filter phục vụ mọi người:

project IN (CLIENTA, CLIENTB, CLIENTC) AND assignee = currentUser() AND status != Done ORDER BY duedate ASC

Vì có currentUser(), khi mỗi trưởng nhóm mở dashboard chung, họ tự động thấy đúng việc của họ. Chị Hà chỉ phải bảo trì một filter thay vì năm. Ngoài ra, chị tạo thêm một filter tổng cho riêng mình để nhìn toàn cảnh:

project IN (CLIENTA, CLIENTB, CLIENTC, CLIENTD, CLIENTE) AND resolution = Unresolved

đưa vào gadget Two Dimensional Filter Statistics với hàng là project, cột là priority. Trong một bảng, chị thấy ngay dự án nào đang có nhiều việc ưu tiên cao chưa xử lý. Bài học: hàm động (currentUser(), membersOf()) giúp bạn xây dashboard mở rộng theo team mà không tăng chi phí bảo trì. Một filter tốt phục vụ được cả chục người.

Hướng dẫn từng bước

Hãy xây một dashboard "PM Command Center" từ đầu:

Bước 1 — Chuyển sang chế độ JQL. Vào Filters → Advanced issue search. Nếu đang ở chế độ Basic (bấm chuột), nhấn nút Switch to JQL để gõ trực tiếp. Đây là nơi bạn thử nghiệm và tinh chỉnh câu query.

Bước 2 — Viết và kiểm tra query. Gõ câu query đầu tiên, ví dụ việc bị bỏ quên:

project = <MÃ_DỰ_ÁN> AND updated <= -14d AND status != Done AND type = Story

Chạy thử, xem số kết quả có hợp lý không. Nếu ra 0 hoặc ra quá nhiều, kiểm tra lại tên trạng thái (phải khớp chính xác, có dấu ngoặc kép nếu có khoảng trắng).

Bước 3 — Lưu thành Saved Filter. Nhấn Save as, đặt tên rõ ràng theo quy ước, ví dụ [PAY] Stale Stories 14d. Tên tốt giúp bạn và đồng đội tìm lại dễ dàng.

Bước 4 — Phân quyền chia sẻ filter. Trong phần Details / Edit permissions, chọn chia sẻ filter với đúng project hoặc group. Nếu không chia sẻ, đồng đội mở dashboard sẽ thấy lỗi "no permission".

Bước 5 — Tạo Dashboard. Vào Dashboards → Create dashboard, đặt tên "PM Command Center", chọn layout hai hoặc ba cột.

Bước 6 — Thêm Gadget. Nhấn Add gadget, chọn ví dụ Filter Results, trỏ tới saved filter vừa tạo, chọn các cột hiển thị (Key, Summary, Assignee, Updated). Lặp lại để thêm Pie Chart (nhóm theo assignee), Created vs Resolved, Two Dimensional.

Bước 7 — Chia sẻ dashboard và đặt lịch. Chia sẻ dashboard với team. Bạn có thể dùng gadget để cả team cùng nhìn một nguồn dữ liệu trong daily và planning, tránh mỗi người một phiên bản sự thật.

Lỗi thường gặp & mẹo

Lỗi 1 — Nhầm giữa trạng thái hiện tại và lịch sử. status = Done chỉ hỏi hiện tại đang Done. Nếu bạn muốn "issue từng bị reopen", phải dùng status CHANGED FROM Done. Rất nhiều PM báo cáo sai vì nhầm hai khái niệm này.

Lỗi 2 — Gõ sai tên field hay value. JQL phân biệt tên trạng thái chính xác. status = "in progress" có thể lỗi nếu tên thật là In Progress. Mẹo: khi gõ, Jira gợi ý autocomplete — hãy chọn từ danh sách thay vì gõ tay.

Lỗi 3 — Dùng ngày cứng thay vì hàm tương đối. Viết created >= "2026-06-01" khiến filter chết cứng, tháng sau vẫn ra kết quả tháng 6. Hãy dùng created >= startOfMonth() để filter tự cập nhật.

Lỗi 4 — Quên ORDER BY. Filter không sắp xếp khiến danh sách lộn xộn, khó đọc trên gadget. Luôn thêm ORDER BY priority DESC hoặc ORDER BY updated ASC để đưa việc quan trọng/cũ nhất lên trên.

Lỗi 5 — Dashboard quá tải. Nhồi 12 gadget vào một dashboard khiến không ai đọc nổi. Nguyên tắc: mỗi dashboard trả lời một nhóm câu hỏi. Tách "Sức khỏe sprint" và "Báo cáo cho sếp" thành hai dashboard riêng.

Mẹo vàng: đặt tên filter theo quy ước [PROJECT] Mục đích Thời gian, ví dụ [PAY] Overdue Bugs. Khi instance có hàng trăm filter, quy ước đặt tên là thứ cứu bạn khỏi hỗn loạn.

Mẹo về resolution: để lọc việc chưa xong một cách chuẩn xác, dùng resolution = Unresolved thay vì status != Done, vì mỗi project có thể có nhiều trạng thái kết thúc khác nhau (Closed, Cancelled, Won't Do) mà đều đã "resolved".

Bài tập thực hành

  • Viết power query. Trong project của bạn, viết câu JQL tìm mọi Bug ưu tiên Highest/High đang mở, sắp xếp theo ngày tạo cũ nhất trước. Ghi lại số kết quả.
  • Đo scope creep. Viết câu query đếm số issue được tạo mới trong sprint hiện tại sau ngày thứ 3 của sprint. So sánh với tổng issue của sprint để tính tỉ lệ phần trăm việc "nhét thêm".
  • Dùng hàm động. Tạo một saved filter dùng currentUser() để mỗi thành viên thấy việc dở dang của riêng mình, rồi chia sẻ với team và nhờ một đồng nghiệp mở thử để xác nhận nó hiển thị đúng phần của họ.
  • Xây dashboard. Tạo dashboard "PM Command Center" với tối thiểu 3 gadget: một Filter Results (stale items), một Pie Chart (phân bổ theo assignee), một Created vs Resolved. Trình bày nó trong buổi họp team gần nhất.
  • Thử toán tử lịch sử. Viết một câu dùng status CHANGED hoặc sprint CHANGED để tìm issue từng bị đưa ra khỏi sprint hoặc từng bị reopen. Ghi lại phát hiện thú vị nhất.

Tóm tắt

JQL biến Jira từ một kho task thành một hệ thống trả lời câu hỏi. Ba trụ cột cần nhớ: hàm thời gian tương đối (-14d, startOfMonth()) giúp filter luôn sống; hàm động (currentUser(), openSprints()) giúp một filter phục vụ cả team; và toán tử lịch sử (WAS, CHANGED) giúp bạn nhìn vào quá khứ của issue chứ không chỉ hiện tại. Những power query như stale items, sprint scope change và bug nghiêm trọng là bộ công cụ hằng ngày của mọi PM giỏi.

Dashboard là nơi bạn trưng bày những câu trả lời đó. Vì dashboard xây trên nền saved filter, chất lượng JQL quyết định chất lượng bức tranh bạn cho cả team và cấp trên nhìn thấy. Như ba tình huống ở Tiki, startup fintech Singapore và agency Đà Nẵng đã cho thấy: một con số được đo đúng và trưng bày rõ ràng có sức thuyết phục vượt xa mọi lời cảm nhận. Hãy bắt đầu bằng việc lưu ba filter và dựng một dashboard ngay hôm nay — đó là bước đầu tiên để bạn thực sự làm chủ Jira.