Custom Query Views
Saved queries built in the Query Builder — what they store, their row actions, and the important caution about them.
Saved Queries
A custom query view is a saved query with a name, built in the Query Builder and re-run on demand.
Where to find it
Architect Panel → Data:
- Query Builder — building a query visually
- Custom Query Views — saved queries, then View Actions on a row
Architect Panel → Data:
- Compilations — a governed alternative for reporting
What it stores
A name, the query itself, a search variant, any special tasks, its filters, and whether it is public.
The important word is query: what is stored is a fully rendered SQL statement, not a description of what to fetch.
Why that matters
Because the tenant and every literal value were baked in at the moment it was saved, and nothing about the row is re-checked against whoever runs it later.
So a saved query runs with the reach it had when it was written, for whoever can run it — not with the reach of the person running it.
Which makes them sensitive
They hold raw SQL that the platform executes, and they are on the API’s protected list for exactly that reason: anybody able to write one could execute arbitrary statements.
Treat the ability to create a custom query view as a privileged permission, not an ordinary reporting one.
Prefer a governed alternative for new reporting
Where the platform offers saved datasets that store a specification rather than a statement, use those instead. A specification is re-authorised against the current reader on every run, which is what you want for reporting that several people use.
Custom query views remain supported and are widely relied on; they are simply not where new work belongs.
Review what exists
Every saved query is a statement somebody wrote once and nobody has read since. A periodic review — what does this return, who can run it, does it still need to exist — is worth the time.
Public is a real decision
A view marked public is available broadly. Given what a saved query is, that is a decision to make deliberately rather than a convenience flag.
Name them so the purpose is obvious
"Open cases over 30 days, by team" rather than "Report 4". A saved query nobody can identify is one nobody dares delete and nobody trusts.
Worked example
An organisation reviewed its saved queries and found eleven, four of which nothing referenced and two of which returned data the current owner should not have been able to see. New reporting was moved to governed datasets and the unused views removed.
Recommendations
- Treat creation as a privileged permission.
- Remember a saved query is a stored statement, not a re-checked request.
- Use governed datasets for new reporting.
- Review what exists and remove what nothing uses.
Building One
A saved query is created from the Query Builder and then given a name and settings of its own.
Where to find it
Architect Panel → Data:
- Query Builder — building a query visually
- Custom Query Views — saved queries, then View Actions on a row
Build the query first
In the Query Builder, where you can see the results as you go. Saving a query you have not run is how a report that returns nothing reaches somebody’s dashboard.
Bound it
A saved query with no date bound returns more every year. Something that ran in a second when it was written can take a minute two years later, and the person who notices is a user.
Where the question is about recent work, say so in the query.
Row actions are a row action
A saved query can carry its own actions on its results — reached through View Actions on the query’s row. Each has a name, a button style and what it does.
That is what turns a list into a worklist: see the twelve overdue cases, and act on one without leaving the list.
Keep actions few and unambiguous
Two or three. A results list with seven buttons per row is one where somebody clicks the wrong one, and on a list of records that matters.
Check the columns are readable
A query returning internal identifiers and raw codes is a query somebody has to interpret. Return the names people use, and only the columns that are needed to decide something.
Run it as somebody else
The critical test, given how saved queries work. Confirm what a different person sees when they run it, because the query does not narrow itself to them.
Test the empty case
A list with no rows should say so clearly. An empty table looks like a fault, and it generates a support contact every time.
Write down what it is for
Alongside the name. Six months later somebody will ask whether this query still means what its title says, and the answer is much easier if the intent was recorded.
Worked example
A saved query returning overdue cases was bounded to the last twelve months, given two row actions — assign and close — and tested by three people with different access. One of them saw cases from another team, which was corrected before the query was shared.
Recommendations
- Run it in the builder before saving.
- Bound it by date so it does not grow forever.
- Two or three row actions, no more.
- Run it as somebody else before sharing it.
The Query Builder
The Query Builder assembles a query visually — choosing tables, joining them, filtering and selecting columns.
Where to find it
Architect Panel → Data:
- Query Builder — building a query visually
- Custom Query Views — saved queries, then View Actions on a row
Architect Panel → Data:
- Datastores — the tables being queried
Start from the question
Written in a sentence. "Which cases opened this month are still unassigned" is a question you can build; "case data" is not, and it produces a query nobody can check.
Start narrow
One table, a filter, a few columns. Run it, confirm the rows are what you expect, then add. Building a five-table query and then discovering it returns nothing is an afternoon; building it in five steps is twenty minutes.
Joins are where it goes wrong
Two symptoms, both common:
- Too many rows — a join matching more than one row on the other side multiplies the result, and totals become wrong rather than absent.
- Too few rows — a join that requires a match drops records that have none.
Check the row count against something you know. If a query about cases returns more rows than you have cases, a join is multiplying.
Filter early
Restricting rows before joining is both faster and easier to reason about. A query filtered at the end has already done the work.
Return only the columns you need
Every extra column is data fetched, transferred and rendered. For a list somebody reads, five columns is usually enough; twenty is a spreadsheet nobody looks at.
Beware totals across joins
Summing a value from a table that has been multiplied by a join gives a total that is confidently wrong. It is the most consequential query mistake, because the number looks plausible.
Check any total against a small case you can count by hand.
Watch how long it takes
A query that takes several seconds in the builder will take longer with more data and several people running it. If it is slow while you are building it, it will not get better.
Check it against something you know
Pick a record you can verify by hand and confirm the query treats it correctly. That is worth more than reading the query, because it tests what it does rather than what you meant.
Worked example
A query joining cases to their notes returned four times as many rows as there were cases, and the resulting total was four times too high. Reducing the join to one note per case fixed it. The total was then checked against a case counted by hand.
Recommendations
- Write the question as a sentence first.
- Build one step at a time, running each.
- Check the row count against something you know.
- Verify any total by hand on a small case.