Blog article

Advanced filtering — nested conditions, OR branches, and subqueries

Published on December 1, 2024

Real questions about business data rarely look like "customers where status equals active." They look like "customers where status is active or pending and the most recent order is from before last quarter, excluding anyone on the do-not-contact list." A filter UI that only handles the simple cases forces users either to accept approximate answers or to drop into a reporting tool to ask the real question. Advanced filtering is the difference between those two worlds, and it's where the query builder starts to feel like a proper analytical tool.

The first upgrade over basic filters is nested conditions. AND and OR groups can be combined and nested to any depth. A query for priority customers might mean "(customer tier = Gold OR customer tier = Platinum) AND (annual revenue > threshold OR strategic flag = true)." That structure has two levels and two different logical operators, and the builder lets you express it directly rather than approximating it. Each group is visible as a nested block in the UI, so the structure of the question is the structure of the query.

OR on the same field solves one of the small annoyances that makes naive filter UIs feel clunky. "Status is Open, Pending, or Awaiting Review" is one filter, not three — the builder expresses it as a single "is in list" condition against the property. Similarly, multiple filters on the same property let you say "amount > 100 AND amount < 1000" without fighting the UI. For numeric and choice properties, in-list and not-in-list operators handle the bulk "any of these" and "none of these" cases cleanly.

Reference-column filters cross from one type into the properties of a related type. Filtering invoices by a field on the related customer — invoices where customer.country = Germany — is a native operation in the builder, not something you approximate with a subquery. Because relationships are first-class in the data model, the builder walks them for you. Several hops are permitted, within reason: invoices where customer.salesRep.region = EMEA is a readable condition rather than an impressive feat. For data sets of any complexity, this is where the query builder earns its keep.

Subqueries handle the cases where you want to filter on "the result of another question." A subquery is a reference to another saved query — or to a query defined inline — and a filter can say "records whose related object is in the result set of this other query." That makes otherwise complicated asks clean. Customers whose most recent order is in the "high-margin this year" query is three English words in the builder and zero lines of code. Subqueries also make sophisticated reuse possible: the "high-margin this year" query is maintained in one place and used as a filter component across multiple other queries, so refining it propagates everywhere.

Date filters have their own set of upgrades because dates are where advanced filtering most often runs out of steam in other tools. Our date filters understand relative expressions — "within the last 30 days," "in the next quarter," "before the end of the fiscal year" — and a growing library of past-date presets covers the common cases: previous month, previous year, last seven days, last quarter. Dates in filters can also use the inline expression language for anything the presets don't cover — end of the current quarter minus two weeks is a valid filter value.

Filter parameters can reference the logged-in user or any other expression-scope variable. A single query named My open tasks behaves correctly for every user who opens it, because the condition is assignee = currentUser rather than a hard-coded name. The same pattern handles current date, current tenant, current region, and any other context the expression engine knows about. One query definition, personalized results per user — and no per-user variants to maintain.

Persistent filter state is the small usability touch that matters in daily work. Apply a filter, navigate to a record, come back — the filter is still where you left it. The filter state is part of the view's URL, so sharing a specific filtered view with a colleague is a single copy-paste.

Advanced filtering also lives behind the REST API. The same nested-condition notation the builder produces can be sent in API calls, which means a partner integration or a custom frontend can express the same sophistication the UI exposes, without degrading to a simpler subset. That matters for teams that want to build external tools on top of the platform — the power users' query vocabulary is the integrators' query vocabulary, too.

Between the query builder, advanced filtering, and saved queries, the platform covers the vast majority of analytical questions business users would otherwise take to a separate reporting tool. Subqueries, nested conditions, and cross-relationship filters together are enough to answer almost anything that doesn't need full-scale OLAP machinery. For the cases that do, the REST API and spreadsheet exports hand the data cleanly to the tools that specialize in them. Most of the time, though, the builder is already the right place.