Our engine never sees your warehouse password
datahashi

BlogQuerying

Semantic Query 101: metrics × dimensions × filters

Introduce the semantic query triad so any consumer can ask the same question the same way.

The datahashi team3 min read

A semantic query is how every consumer asks for a certified number without writing SQL. The shape is simple on purpose: metrics, dimensions, and filters. Master that triad and dashboards, notebooks, and agents speak the same language.

The triad

Metrics are the measures you want - named, certified, and published. You request them by name, not by inventing an aggregation expression. One metric might be a count of completed orders; another might be a sum of net revenue. The definition lives in the published model.

Dimensions are the ways you slice those metrics - time buckets, region, channel, product category. You only request dimensions the metric allows. That restriction is the point. It keeps callers inside the grain the definition supports.

Filters narrow the rows that contribute to the measure - a date range, a status, a country code. Filters are also constrained by the metric contract so callers cannot smuggle unsupported predicates into the request.

Together: which measures, broken out how, restricted how. That is the entire question surface for a semantic query.

Why this beats free-form SQL for shared truth

SQL is expressive. Expressiveness is how two teams get two numbers for one English sentence. A semantic query trades some expressiveness for a shared contract. Callers cannot invent joins. They cannot change the measure definition inline. They ask for what was published.

datahashi keeps that contract consistent across REST, the console, and MCP. The request shape does not change because the client did. MCP tools list_catalog, describe_metric, and run_semantic_query never accept or return SQL. An agent discovers metrics, reads their allowed dimensions and filters, then runs the same shape a human would send from the console.

A mental walkthrough

Suppose you want completed orders by region for last month. You do not open a schema browser and invent joins. You:

  1. Confirm orders_completed (or your equivalent certified name) exists via the catalog.
  2. Describe the metric to see allowed dimensions and filters.
  3. Run a semantic query: metric orders_completed, dimension region, filters for the last month window.

The serving layer resolves that request against the published YAML artifact. The warehouse still holds the transforms underneath. datahashi stays thin: it serves meaning, it does not become a second transformation system.

Same triad, many consumers

A BI panel encodes the triad in its query config. An agent encodes it in an MCP call. An internal app encodes it in a REST payload. If all three use the same metric name, dimensions, and filters, they should receive the same number. That is the governance payoff.

Metering exists so you can inspect who ran which semantic queries. When numbers disagree, compare the requests first. Divergent dimensions or filters are more common than “the warehouse being wrong.”

What beginners should not overload

Do not treat the triad as a place to reimplement every SQL habit. Window functions, arbitrary cross-joins, and one-off expressions belong upstream or in ad-hoc analysis - not in the certified path. Rollups have shipped, and a semantic query is useful without one. A p99 latency target is not part of the contract.

Start with one metric, one or two dimensions, and clear filters. Teach every consumer that vocabulary. Once the triad is muscle memory, adding metrics is additive - not a new dialect per tool.

The habit to build

Before anyone writes SQL for a recurring question, ask: is there a certified metric? If yes, issue a semantic query. If no, model and publish one, then query it. Humans and agents get the same metric without hallucinated SQL - because the query never asked them to write SQL in the first place.

Product notes

An occasional email when we ship something or write something worth reading.