JQL Cheat Sheet: The Queries You Keep Googling
For Jira admins who know JQL but forget the syntax every time
This isn’t a JQL tutorial. You already know what JQL is.
This is the page you bookmark and come back to when you can’t remember:
- Why your
!=query is missing issues - Whether
startOfWeek()means Sunday or Monday - That one date function syntax you always forget
- How to search for issues in an Epic (and why it’s different in Cloud vs Data Center)
Everything here works on both Jira Cloud and Data Center unless noted otherwise.
The 7 Gotchas That Catch Everyone
!= Doesn’t Include Empty Values
This query looks correct:
assignee != "john"
But it’s missing every unassigned issue in your project.
Jira follows SQL NULL logic. NULL != "john" returns false, not true. This is by design and won’t change — Atlassian marked it “Won’t Fix” in 2019.
assignee != "john" OR assignee is EMPTY
Same applies to NOT IN:
-- Wrong (missing unassigned):
assignee NOT IN ("john", "jane")
-- Correct:
assignee NOT IN ("john", "jane") OR assignee is EMPTY
startOfWeek() Returns Sunday, Not Monday
created >= startOfWeek()
You expected Monday. Jira gives you Sunday.
Jira defaults to US locale where Sunday is the first day of the week. There’s an ISO8601 setting in Look and Feel, but it’s buggy and doesn’t always work.
-- Monday to Friday (actual work week):
created >= startOfWeek("+1d") AND created <= endOfWeek("-1d")
-- Monday to Sunday:
created >= startOfWeek("+1d") AND created <= endOfWeek("+1d")
The +1d shifts Sunday to Monday. Yes, it's annoying.
WAS and CHANGED Only Work on 6 Fields
You want to find issues where Sprint changed:
Sprint CHANGED FROM "Sprint 1" TO "Sprint 2"
Error. The WAS and CHANGED operators only work with:
- Assignee
- Fix Version
- Priority
- Reporter
- Resolution
- Status
That's it. No Sprint, no Issue Type, no Due Date, no Custom Fields.
WAS/CHANGED are unreliable in team-managed (next-gen) projects. See JRACLOUD-72180.
Special Characters Don't Work in Text Search
summary ~ "[URGENT]"
This searches for URGENT, ignoring the brackets entirely.
Jira's Lucene index strips special characters. They're not stored, so you can't search for them.
Characters that get ignored: + - . , ; ? | * / % ^ $ # @ [ ] ( ) { }
Escaping doesn't help — this is a known limitation since 2011, marked "Won't Fix":
summary ~ "\\[URGENT\\]"
Wildcards Can't Start a Word
-- Works: summary ~ "error*" -- Finds: error, errors, errorCode -- Doesn't work: summary ~ "*error" -- FORBIDDEN summary ~ "?est" -- FORBIDDEN
Jira explicitly blocks leading wildcards because they're extremely slow on large instances.
summary ~ "\"deployment failed\""
An Issue Can Be in Two Sprints Simultaneously
When you close a sprint, incomplete issues move to the next sprint. But they keep their link to the old sprint too.
-- Returns issues that were in Sprint 5, including those now in Sprint 6: sprint = "Sprint 5" -- Only issues that finished in Sprint 5: sprint = "Sprint 5" AND sprint NOT IN openSprints()
To find backlog items:
project = "PROJ" AND (sprint IS EMPTY OR sprint NOT IN (openSprints(), futureSprints())) AND resolution IS EMPTY
Epic Queries Are Different in Cloud vs Data Center
Data Center:
"Epic Link" = PROJ-123
Cloud (2023+):
parent = PROJ-123
Atlassian deprecated Epic Link in Cloud and replaced it with parent. Old saved filters still work, but you can't create new ones with Epic Link.
Cloud:
parent = PROJ-123 OR parentEpic = PROJ-123
Data Center:
"Epic Link" = PROJ-123 OR parent IN (issueFunction in issuesInEpics("key = PROJ-123"))
(Requires ScriptRunner for the subtasks part)
Copy-Paste Queries
Personal Work
-- Everything assigned to me (open) assignee = currentUser() AND resolution IS EMPTY -- My issues in current sprint assignee = currentUser() AND sprint IN openSprints() -- Where I'm mentioned (last 7 days) (text ~ currentUser() OR comment ~ currentUser()) AND updated >= -7d -- Issues I'm watching watcher = currentUser() AND resolution IS EMPTY -- Reported by me, still open reporter = currentUser() AND resolution IS EMPTY
Dates and Deadlines
-- Overdue duedate < now() AND resolution IS EMPTY -- Due this week duedate >= startOfWeek() AND duedate <= endOfWeek() -- Created today created >= startOfDay() -- Updated in last 24 hours updated >= -24h -- Created more than 30 days ago, still open created <= -30d AND resolution IS EMPTY -- Resolved last month resolved >= startOfMonth(-1) AND resolved <= endOfMonth(-1) -- No activity in 90 days updated <= -90d AND resolution IS EMPTY
Status History
-- Was ever In Progress
status WAS "In Progress"
-- Currently Done, was In Progress at some point
status = "Done" AND status WAS "In Progress"
-- Status changed in the last 7 days
status CHANGED AFTER -7d
-- Moved to Done this week
status CHANGED TO "Done" AFTER startOfWeek()
-- Reopened issues (was resolved, now not)
status WAS IN ("Resolved", "Done", "Closed") AND resolution IS EMPTY
Sprint and Backlog
-- Current sprint sprint IN openSprints() -- Current sprint, specific project sprint IN openSprints() AND project = "PROJ" -- Backlog (not in any active/future sprint) (sprint IS EMPTY OR sprint NOT IN (openSprints(), futureSprints())) AND resolution IS EMPTY AND project = "PROJ" -- Completed in closed sprints (not carried over) sprint IN closedSprints() AND sprint NOT IN openSprints() AND resolution IS NOT EMPTY -- Added to sprint mid-sprint (requires status history) sprint IN openSprints() AND NOT status WAS "To Do" ON startOfWeek()
Team Queries
-- All issues for a group
assignee IN membersOf("dev-team")
-- Unassigned in project
project = "PROJ" AND assignee IS EMPTY AND resolution IS EMPTY
-- Created by my team this month
reporter IN membersOf("dev-team") AND created >= startOfMonth()
-- High priority without assignee
priority IN (Highest, High) AND assignee IS EMPTY AND resolution IS EMPTY
Epic and Hierarchy
Cloud:
-- All issues in an Epic parent = PROJ-123 -- Issues without an Epic parent IS EMPTY AND issuetype != Epic AND issuetype NOT IN subtaskIssueTypes() -- All Epics without children issuetype = Epic AND NOT parent = *
Data Center:
-- All issues in an Epic "Epic Link" = PROJ-123 -- Issues without an Epic "Epic Link" IS EMPTY AND issuetype != Epic AND issuetype NOT IN subtaskIssueTypes() -- Subtasks of a specific parent parent = PROJ-456
Text Search
-- Word in summary summary ~ "migration" -- Exact phrase summary ~ "\"database migration\"" -- In summary OR description summary ~ "error" OR description ~ "error" -- In comments only comment ~ "workaround" -- Multiple words (AND logic) text ~ "deployment production failed" -- Wildcard (words starting with) summary ~ "API*"
Filters and Cleanup
-- Issues with attachments attachments IS NOT EMPTY -- Issues without components component IS EMPTY AND project = "PROJ" -- Flagged/impediment flagged = Yes -- Exclude subtasks from results issuetype NOT IN subtaskIssueTypes() -- Issues with external links issueLink IS NOT EMPTY -- Specific link type issueLinkType = "blocks"
Date Functions Reference
| Function | Returns | Example |
|---|---|---|
now() |
Current time (milliseconds) | updated > now() - 1h |
startOfDay() |
Today 00:00 | created >= startOfDay() |
endOfDay() |
Today 23:59:59 | duedate <= endOfDay() |
startOfWeek() |
Sunday 00:00 | created >= startOfWeek() |
endOfWeek() |
Saturday 23:59 | duedate <= endOfWeek() |
startOfMonth() |
1st of month | created >= startOfMonth() |
endOfMonth() |
Last day of month | duedate <= endOfMonth() |
startOfYear() |
January 1 | created >= startOfYear() |
endOfYear() |
December 31 | duedate <= endOfYear() |
Offsets
All functions accept offset parameters:
startOfDay("-1d") -- Yesterday 00:00
startOfDay("+1d") -- Tomorrow 00:00
startOfWeek("-1w") -- Last week
startOfMonth("-1M") -- Last month
startOfWeek("+1d") -- Monday (workaround for Sunday default)
Relative Dates
-7d -- 7 days ago -2w -- 2 weeks ago -1M -- 1 month ago -1y -- 1 year ago -- Combine with comparison: created >= -7d -- Created in last 7 days updated <= -30d -- Not updated in 30 days
Absolute Dates
created >= "2024-01-15" created >= "2024-01-15 14:30"
Cloud vs Data Center Differences
| Feature | Cloud | Data Center |
|---|---|---|
| Epic queries | parent = EPIC-123 |
"Epic Link" = EPIC-123 |
parentEpic function |
✅ Works | ❌ Not available |
| WAS/CHANGED reliability | ⚠️ Buggy in team-managed | ✅ Stable |
issueFunction (ScriptRunner) |
❌ Not available | ✅ With ScriptRunner |
portfolioChildIssuesOf |
✅ Built-in | ✅ With Advanced Roadmaps |
Everything else — operators, date functions, text search — works identically.
Performance Tips
1. Always Add Project When Possible
-- Slower (scans everything): status = "Open" -- Faster (scoped to project): project = "PROJ" AND status = "Open"
2. Use Specific Fields Instead of text
-- Slow (searches all text fields): text ~ "deployment" -- Faster (searches specific fields): summary ~ "deployment" OR description ~ "deployment"
3. IN Is Faster Than OR Chains
-- Better:
status IN ("Open", "In Progress", "Review")
-- Worse:
status = "Open" OR status = "In Progress" OR status = "Review"
4. Avoid Leading Wildcards
-- Forbidden and would be slow anyway: summary ~ "*error" -- OK: summary ~ "error*"
5. ORDER BY Indexed Fields
-- Fast: ORDER BY created DESC -- Potentially slow: ORDER BY "Custom Text Field" ASC
Known Bugs Worth Knowing
| Bug | Description | Status |
|---|---|---|
| JRASERVER-23030 | != excludes empty values |
Won't Fix |
| JRASERVER-25092 | Special character escaping doesn't work | Won't Fix |
| JRACLOUD-72180 | WAS/CHANGED unreliable in team-managed projects | Open |
| JRACLOUD-70567 | startOfWeek() ignores locale |
Closed (partial fix) |
| JRASERVER-63292 | Request: CHANGED on more fields | Gathering Interest |
Quick Reference Card
Operators:
= != > >= < <= IN NOT IN ~ !~ (text contains / doesn't contain) IS IS NOT (for EMPTY/NULL) WAS WAS NOT WAS IN WAS NOT IN CHANGED
Keywords:
AND OR NOT ORDER BY EMPTY NULL (synonyms)
Current User:
currentUser() -- Logged-in user
membersOf("group-name") -- All users in group
Useful Issue Type Filters:
issuetype = Bug issuetype IN standardIssueTypes() issuetype IN subtaskIssueTypes() issuetype NOT IN subtaskIssueTypes()
Useful Resources
Bookmark This Page
You'll be back. Everyone comes back for startOfWeek() syntax at least three times before it sticks.
JQL is powerful once you know the gotchas. These queries save hours every week when you stop fighting the syntax and start copying what works.
Next time you're stuck on a query, Ctrl+F this page. It's faster than the official docs.
Last updated: December 2025
Found this useful? It's part of our work at Votazz where we build tools for Jira administrators.