JQL Cheat Sheet: 67 Queries Tested on Jira Cloud (2026)
On this page
- How a JQL query is built
- Your own work
- Status and resolution
- Dates
- Text
- People and teams
- Sprints and releases
- Epics, parents, subtasks and links
- History: WAS and CHANGED
- Other fields, spaces and sorting
- All 17 operators
- The renamed functions: which work today
- Seven traps, tested
- Build it without typing
- How we tested
A team lead wants to see what everyone else is working on and types assignee != currentUser().
The list looks right. It is short by 56 work items: every one that nobody is assigned to. JQL
reads != as “has a value, and the value is not this”, so the empty ones never make it in.
That is the kind of thing this cheat sheet is for. All 67 queries on this page were run on a
live Jira Cloud site on 13 November 2026, a test site with 162 work items in 12 spaces, with Jira’s
own strict check (/rest/api/3/jql/parse?validation=strict) and a count of what each returned. None
of them failed. The traps further down come with the numbers that show them.
Short answer: a JQL query is clauses of field, operator, value, joined by AND and
OR and sorted with ORDER BY: project = PAY AND statusCategory != Done ORDER BY priority DESC. Use statusCategory for “done or not”, -7d and startOfWeek() for dates, ~ for text,
openSprints() for the running sprint. AND is read before OR, != skips empty fields,
and text search never matches part of a word.
How a JQL query is built
A query is one or more clauses. Each clause names a field, an operator and a value or a
function that returns values. Keywords join the clauses, brackets group them, and ORDER BY
comes last.
Three rules save most of the debugging:
- Quote values with spaces or special characters:
status = "In Review",labels = "select". - AND binds tighter than OR.
statusCategory = Done AND priority = High OR priority = Highestreturned 13 items on our site; with brackets around the two priorities, 4. - A query needs at least one condition when an app or a script runs it through the REST API.
order by keyon its own came back asUnbounded JQL queries are not allowed here. Please add a search restriction to your query.
Your own work
| You want | JQL |
|---|---|
| My open work, most urgent first | assignee = currentUser() AND statusCategory != Done ORDER BY priority DESC, updated DESC |
| What I reported in the last 30 days | reporter = currentUser() AND created >= -30d |
| What I watch and is still open | watcher = currentUser() AND statusCategory != Done |
| Everything I watch | issue in watchedIssues() |
| What I opened recently | issue in issueHistory() ORDER BY lastViewed DESC |
| Viewed in the last week | lastViewed >= -7d |
| Mine or nobody’s in one space | assignee in (currentUser(), EMPTY) AND project = PAY |
issueHistory() returns the work items you opened most recently, up to 50 of them, where Jira’s
recent menu shows 5 (Atlassian’s functions page).
Status and resolution
| You want | JQL |
|---|---|
| Not started | statusCategory = "To Do" |
| Being worked on | statusCategory = "In Progress" |
| Not finished, whatever the workflow | statusCategory != Done |
| Exact statuses | status in ("In Progress", "In Review") |
| Not in two statuses | status not in (Done, Closed) |
| No resolution set | resolution = Unresolved |
| Done but nobody set a resolution | resolution = Unresolved AND statusCategory = Done |
| Resolved but reopened | resolution is not EMPTY AND statusCategory != Done |
Prefer statusCategory to a list of statuses. Every status belongs to To Do, In Progress or Done,
so the query keeps working when someone adds “In Review” or “Released” to the workflow.
resolution = Unresolved is not the same as “not done”. On our site it matched 137 items,
statusCategory != Done matched 131, and the difference was six items sitting in a Done status
(one of them “Released”) with no resolution, because their workflow never sets one. Reports and
gadgets that count “unresolved” count those six as open work forever.
Dates
| You want | JQL |
|---|---|
| Created today | created >= startOfDay() |
| Created this week | created >= startOfWeek() |
| Created in the last 7 days | created >= -7d |
| Open and untouched for a month | updated <= -30d AND statusCategory != Done |
| Overdue | due < now() AND statusCategory != Done |
| Due this week | due >= startOfDay() AND due <= endOfWeek() |
| Open with no due date | duedate is EMPTY AND statusCategory != Done |
| Resolved last month | resolved >= startOfMonth(-1) AND resolved < startOfMonth() |
| A fixed quarter | created >= "2026-01-01" AND created < "2026-04-01" |
Dates go year first. created > "11/01/2026" failed with
Date value '11/01/2026' for field 'created' is invalid. Valid formats include: 'yyyy/MM/dd HH:mm', 'yyyy-MM-dd HH:mm', 'yyyy/MM/dd', 'yyyy-MM-dd', or a period format e.g. '-5d', '4w 2d'. The full
story of relative dates, time zones and the startOf and endOf functions is in
JQL dates.
Text
| You want | JQL |
|---|---|
| A word in the summary | summary ~ "payment" |
| An exact phrase | summary ~ "\"duplicate charge\"" |
| Words that start with refund | summary ~ "refund*" |
| Summary, description and comments | text ~ "timeout" |
| Only in comments | comment ~ "rollback" |
| No description at all | description is EMPTY |
| Without a word | summary !~ "test" |
Text search works on whole words, after Jira cuts them to a root form (“customize” is stored as “custom”, Atlassian’s text search page explains). What that means in practice, from our tests:
summary ~ "pay"found nothing, though one summary says “retry failed payment”."pay*"found it. A star at the start,"*etry", found nothing.?stands for one letter:"pay?ent"found the payment item.- Common English words are left out of the index.
summary ~ "the retry"matched the same three items as"retry". Atlassian’s own example: a search for “VSX will crash” also finds “VSX will not crash”, because “will” and “not” are on the list. - A phrase needs inner quotes escaped with a backslash, as in the table.
People and teams
| You want | JQL |
|---|---|
| Unassigned and open in one space | assignee is EMPTY AND project = PAY AND statusCategory != Done |
| Someone in a group | assignee in membersOf("jira-users-simplify-demo") |
| I reported it, someone else has it | reporter = currentUser() AND assignee != currentUser() |
| Reassigned this week | assignee changed AFTER -7d |
| I voted for it | voter = currentUser() |
| Most votes first | votes > 0 ORDER BY votes DESC |
Put your own group name in membersOf(). A group that does not exist is an error, not an empty
result. For the difference between the reporter and the assignee, and why reporter != assignee
does not do what it reads like, see Jira reporter vs assignee.
Sprints and releases
| You want | JQL |
|---|---|
| In a running sprint | sprint in openSprints() |
| Planned for a later sprint | sprint in futureSprints() |
| Carried over into the running sprint | sprint in closedSprints() AND sprint in openSprints() |
| Open work in no sprint | sprint is EMPTY AND statusCategory != Done AND project = PAY |
| In versions not released yet | fixVersion in unreleasedVersions() |
| In the next release of one space | fixVersion = earliestUnreleasedVersion(PAY) |
| Done but in no release | fixVersion is EMPTY AND resolution = Done |
openSprints() covers every running sprint the site has, so add project = PAY when you want one
team. More sprint queries, and what counts as “done” at the end of a sprint, are in our
Jira sprints guide.
Epics, parents, subtasks and links
| You want | JQL |
|---|---|
| Children of one epic | parent = PAY-1 |
| Open epics | type = Epic AND statusCategory != Done |
| All subtasks | hierarchyLevel = -1 |
| Subtask types, or the standard ones | issuetype in subTaskIssueTypes() / issuetype in standardIssueTypes() |
| Linked to one work item | issue in linkedIssues("PAY-1") |
| Blocking one work item | issue in linkedIssues("PAY-1", "is blocked by") |
| Blocked and still open | issueLinkType = "is blocked by" AND statusCategory != Done |
hierarchyLevel uses numbers: 1 for epics (the parent level), 0 for stories and tasks, -1 for
subtasks. Levels above epic made in Plans are not covered. Grandchildren, "Epic Link" and why
some link queries return nothing are in JQL for parents, epics and linked issues.
History: WAS and CHANGED
| You want | JQL |
|---|---|
| Was in progress before this week | status WAS "In Progress" BEFORE startOfWeek() |
| Moved back to To Do in two weeks | status CHANGED FROM "In Progress" TO "To Do" AFTER -14d |
| Finished last month | status CHANGED TO Done DURING (startOfMonth(-1), endOfMonth(-1)) |
| Ever assigned to me | assignee WAS currentUser() |
| Priority changed this week | priority CHANGED AFTER -7d |
WAS and CHANGED read the history. Atlassian lists six fields for WAS: assignee, fix version,
priority, reporter, resolution and status. labels WAS payments failed on our site: Jira answered
that history searches do not support the labels field. The predicates (AFTER,
BEFORE, DURING, ON, BY, FROM, TO) are covered in
JQL WAS and CHANGED.
Other fields, spaces and sorting
Labels, components and other fields
| You want | JQL |
|---|---|
| No labels | labels is EMPTY |
| Either of two labels | labels in (payments, checkout) |
| Without a label, unlabelled included | labels not in (payments) OR labels is EMPTY |
| No component in one space | component is EMPTY AND project = PAY |
| With attachments | attachments is not EMPTY |
| Stories nobody estimated | "Story point estimate" is EMPTY AND type = Story AND statusCategory != Done |
Fields with spaces in their names go in quotes. On a company-managed space the field is often
"Story Points"; on a team-managed one, "Story point estimate". Both exist on our site. A field
can also be named by its ID, cf[10016].
Spaces and permissions
| You want | JQL |
|---|---|
| Spaces I lead | project in projectsLeadByUser() |
| Spaces where I hold a role | project in projectsWhereUserHasRole("Administrators") |
Sorting
| You want | JQL |
|---|---|
| Board order | project = PAY ORDER BY Rank ASC |
| Priority, then oldest first | project = PAY ORDER BY priority DESC, created ASC |
ORDER BY takes several fields, each with ASC or DESC. It changes the order only, not which
items match.
All 17 operators
| Operator | Meaning | Example |
|---|---|---|
= | is exactly | status = Done |
!= | has a value, and not this one | priority != Low |
> >= < <= | after or before, more or less | due < now() |
IN | any of a list | status in ("To Do", "In Progress") |
NOT IN | none of a list, empty excluded | labels not in (payments) |
~ | contains words | summary ~ "refund*" |
!~ | does not contain words | summary !~ "test" |
IS | is empty | assignee is EMPTY |
IS NOT | is not empty | attachments is not EMPTY |
WAS | had this value at some point | assignee WAS currentUser() |
WAS IN | had any of these values | status WAS IN ("In Review", QA) |
WAS NOT | never had this value (in a period) | status WAS NOT Done BEFORE -7d |
WAS NOT IN | never had any of these | status WAS NOT IN (Done, Closed) |
CHANGED | the value changed | priority CHANGED AFTER -7d |
IS and IS NOT only take EMPTY (or its synonym NULL). ~ and !~ only work on text fields.
The renamed functions: which work today
In 2026 Atlassian started calling issues “work items” and projects “spaces”. The JQL reference now lists new names, with a warning on the keywords page that “some JQL entries using the new terms may not work yet”. We ran each name exactly as the reference prints it on our site on 13 November 2026.
| Old name | New name in the docs | New name works? |
|---|---|---|
issueHistory() | workItemHistory() | Yes |
watchedIssues() | watchedWorkItems() | Yes |
votedIssues() | votedWorkItems() | Yes |
projectsLeadByUser() | spacesLeadByUser() | Yes |
projectsWhereUserHasRole() | spacesWhereUserHasRole() | Yes |
projectsWhereUserHasPermission() | spacesWhereUserHasPermission() | Yes |
standardIssueTypes() | standardWorkTypes() | Yes |
subTaskIssueTypes() | subtaskWorkTypes() | Yes |
issuesWithRemoteLinksByGlobalId() | workItemsWithRemoteLinksByGlobalId() | Yes |
issuekey | workItemKey | Yes |
issueLinkType | workItemLinkType | Yes |
projectType | spaceType | Yes |
project | spaceJira | Yes |
linkedIssues() | linkedWorkItems() | No: Unable to find JQL function 'linkedWorkItems(SPR-10)'. |
parentProject | parentSpace | No: Field 'parentSpace' does not exist or you do not have permission to view it. |
The obvious guess fails too: space = SPR returned Field 'space' does not exist or you do not have permission to view it. The old names all still work, so saved filters, boards and
Automation rules are safe. For new queries, keep the old names until the new ones work everywhere.
Seven traps, tested
!=andNOT INskip empty fields. 86 instead of 142 in our test. AddOR field is EMPTY.- AND before OR. 13 instead of 4. Put brackets around every OR.
- Unresolved is not “not done”. Six done items had no resolution. Use
statusCategory. - No field-to-field comparison.
reporter != assigneereturned all 106 assigned items, including the 10 where both were the same person.reporter = assigneereturned 0. - No part words.
"pay"missed “payment”. Use"pay*". - Dates are year first. US-style dates are an error.
- Reserved words need quotes.
labels = selectfailed withError in the JQL Query: 'select' is a reserved JQL word. You must surround it in quotation marks. JQL reserves 195 words, among themselect,order,limit,user,dateandempty. Characters such as@or brackets inside a text search go in quotes too, and a bracket needs two backslashes:summary ~ "\\(text".
Build it without typing
If you would rather click than type, our free JQL builder writes a query from a form and explains one you paste, clause by clause, with the traps above flagged. It runs in your browser and sends nothing anywhere.
Inside Jira, our app JQL Blocks does the same with blocks: AND, OR, groups and NOT, the JQL written beside them, and sprint start and end dates as real Jira fields that plain JQL does not have.
How we tested
- Site: a Jira Cloud test site on the Standard plan, 162 work items in 12 spaces (software, service and business), on 13 November 2026.
- Syntax: every query on this page through
POST /rest/api/3/jql/parse?validation=strict, which also checks that fields, values and functions exist. 67 of 67 passed. - Results: each query counted with
POST /rest/api/3/search/approximate-count; the traps were then checked one by one in the search results. - Reference: Atlassian’s JQL fields, operators, functions, keywords, advanced search and text search pages, read on the same day.
Space keys, group names and work item keys such as PAY-1 are from our site. Replace them with
yours.
Frequently asked questions
How do I write a JQL query?
Open Jira search, switch to JQL, and write clauses of the form field, operator, value: project = PAY, status = "In Review", due < now(). Join clauses with AND or OR, group them in brackets, and end with ORDER BY to sort, for example project = PAY AND statusCategory != Done ORDER BY priority DESC.
Is JQL the same as SQL?
No. JQL looks like a SQL WHERE clause, but there is no SELECT, no JOIN and no GROUP BY, and you cannot compare two fields with each other: reporter != assignee is read as "reporter is not a person called assignee". JQL only picks work items and sorts them; Jira decides which columns you see.
What does statusCategory mean in JQL?
Every status belongs to one of three categories: To Do, In Progress and Done. statusCategory != Done finds unfinished work whatever your workflow calls its statuses, so the query keeps working when someone adds a status such as In Review or Released.
Why does != hide work items with an empty field?
In JQL, != and NOT IN only match work items where the field has a value. On our test site assignee != currentUser() returned 86 items and left out 56 unassigned ones. Add OR assignee is EMPTY to keep them; the same goes for labels, components and versions.
How do I search for part of a word in JQL?
You cannot match the middle of a word. Text search works on whole words, so summary ~ "pay" did not find "payment" in our test. Put * at the end, summary ~ "pay*", or ? for a single letter. A * at the start, as in "*etry", returned nothing.
Do the new names in the Jira docs work in JQL?
Most do. In November 2026 workItemHistory(), watchedWorkItems(), spacesLeadByUser(), workItemKey and workItemLinkType all worked. linkedWorkItems() and parentSpace failed with errors, and space = KEY failed too, so keep linkedIssues(), parentProject and project.