Feature

Joinable Data Marts

Declare the join once. Every report inherits it.

A hand-written join onto a one-to-many table can double revenue without an error. Declare the relationship between two Data Marts once, with its join keys and how each joined field collapses to one value, and every report on the source picks the joined fields. Adding a column never multiplies rows. Documentation

Get started free

Joinable Data Marts

Why OWOX

When a question needs a column from another Data Mart, the usual fix is one more SQL Data Mart, or a hand-written join that silently doubles revenue on a one-to-many table. Declare the relationship once, and every report on the Data Mart picks the joined fields.

  • Each joined Data Mart is collapsed to one row per key before it is added, so adding a column never multiplies your rows, and the SQL is one click away.
  • The Data Owner sets the join keys and how each field collapses; business users and AI assistants pick only through joins the Data Owner declared.
  • Chains count: if Campaigns joins Orders and Orders joins Products, Products fields are one tick away in every Campaigns report.

Trust

The Data Partner You Can Trust

users

176K Source: Internal OWOX data as of 2026-10-02

Executives and data analysts across 20+ industries

G2 rating

4.9★2

“A trusted data analytics partner” — verified review

npm installs

165K3

In Open Source We Trust

Customers

Declared Once

Every hand-written join is one more copy to keep right

Revenue sits in one Data Mart, the product category two hops away. Without a declared join, you write another SQL Data Mart for that one question and the copies drift. Or a one-to-many join doubles revenue, and nothing flags it.

THE DATA OWNER

Declare the relationship, not another query

In the source Data Mart's Data Setup, click Join Data Mart, pick a target on the same storage and pair the join keys. Then set each joined field's name, how its rows collapse to one value (its Dedup) and the aggregations reports may use.

Declare the relationship, not another query

Written once on the Data Mart, inherited by every report.

THE BUSINESS USER

The next column is already in the picker

In the OWOX Extension for Google Sheets, joined fields sit in their own group under the Data Mart's native fields. Tick Customer Segment or Region and run: the report never holds more rows than the source Data Mart.

The next column is already in the picker

A column from another Data Mart is one more tick.

No second model to keep in sync — A semantic layer such as LookML, dbt MetricFlow or Cube keeps joins in a separate model you write and maintain. Here the relationship lives on the Data Mart the Data Owner already owns, next to its aliases and descriptions.

For Data Owners

For Data Owners

One declaration instead of a join per report

The join lives on the Data Mart, not in a copy of a query. Every report, destination and AI assistant reuses it, so there is no second copy to drift from the first.

Chains, not just pairs

Chains, not just pairs

If Orders joins Customers and Customers joins Traffic Sources, Traffic Sources fields are available in every Orders report. The Graph view shows each Data Mart reachable from the source. A chain that loops back gets a Loop badge and adds no fields.

Worked example: Orders to Sessions on session_id

Worked example: Orders to Sessions on session_id

On Orders (E-Commerce), click Join Data Mart and pick Sessions. Pair session_id with session_id, both STRING. When one column is not enough to match rows, add another pair, and rows must match on both. A pair whose types do not match cannot be saved.

Decide how each joined field collapses

Decide how each joined field collapses

A joined Data Mart can hold several rows per key, such as several orders per customer. Each field's Dedup collapses them to one value before they are added. By default numbers are summed, dates take the latest and text lists every value; an average, a minimum or a count answers other questions.

For Business Users

For Business Users

Take the column, not the query

Joined fields arrive in the report editor you already use, under names the Data Owner chose. You pick columns; the joins and their definitions stay the Data Owner's.

Native and joined fields in one list

Native and joined fields in one list

In the report editor, the Data Mart's own fields sit on top, and each relationship adds a group under the name the Data Owner gave it: Sessions, and Session Ad Spend reached through it. Sort by a joined field like any other.

Right inside Google Sheets

Right inside Google Sheets

In the OWOX Extension for Google Sheets, open the Customers group on the Orders Data Mart, tick Customer Segment and Region, then Create & Run. The same joined fields reach Microsoft Excel, Data Studio, email, Slack and Teams reports.

The SQL behind the number, one click away

The SQL behind the number, one click away

Preview SQL on the report shows the exact query that runs in your storage, with a link from each joined Data Mart back to its definition. Copy as Data Mart turns it into a standalone SQL Data Mart.

Editions

Compare plans

Individual

Your analyst, just for you.

$295 / month

Try free

Team

Your analyst for your leadership team.

$790 / month

Book a demo

Scale

Your analyst for the whole company.

Let's talk

Book a demo

See full pricing & comparison →

Why teams pick OWOX

Everything business needs

Adding a column can't multiply rows

Each joined Data Mart is collapsed to one row per key before it is added, so the result never holds more rows than the source Data Mart.

Only joins the Data Owner declared

Business users and AI assistants connected through OWOX MCP pick joined fields; they cannot create a join of their own.

SQL you can read and keep

Preview the generated SQL from the report, the Destinations tab or Run History, and keep it as a standalone SQL Data Mart with Copy as Data Mart.

Runs in your warehouse

The join is SQL executed in your own storage: Google BigQuery, Snowflake, AWS Redshift, AWS Athena or Databricks. Both Data Marts sit on the same one.

FAQ

Frequently asked questions

How is this different from a semantic layer?

A semantic layer such as LookML, dbt MetricFlow or Cube keeps joins in a separate model you write, then keep in sync. Here the Data Owner declares the relationship on the Data Mart they already own. It extends a report by columns; report logic beyond that stays in SQL Data Marts.

Can I set up a join myself, without writing SQL?

Yes, if you have maintenance access to both Data Marts. On the source Data Mart, pick the other Data Mart, pair the columns that match, and check how each joined field collapses to one value per key (each starts with a default). That setting, the field's Dedup, is the one to learn first: it decides what a joined number means. OWOX generates the SQL from these settings.

What do I need before I join two Data Marts?

Two different Data Marts on the same storage, maintenance access to both, and a column in each that matches, of a compatible type. The joined fields reach reports once the other Data Mart is published. A declared primary key is recommended but not required: without one, OWOX can only warn that a joined count may be off, not say which way.

How do I keep a join working as my Data Marts change?

You keep a join working from one place, the source Data Mart: the relationship is defined there and available to every report built on it, and maintenance access to that Data Mart is enough to edit it. If a Data Mart in a chain is still a draft or a join has no keys, the relationship shows a badge saying so, and its fields stay out of reports until you fix it. Adding a relationship changes no existing report until someone picks one of its fields.

How do I check a joined number?

Open Preview SQL on the report, or open a run in Run History, to see the exact SQL sent to your storage. Each joined Data Mart sits in its own block with a link back to its definition, and you can paste the query into your warehouse console to check it.

Can an AI assistant use joined fields?

Yes, through OWOX MCP. The assistant selects joined fields from relationships the Data Owner declared and cannot create a join of its own. When the Data Owner writes a relationship description in the Description tab, the assistant reads it with the join keys, so it knows what the join means, not only how rows match.

What users are saying

Every claim has a receipt.

Real things real customers said — each quote pinned to a specific claim, straight from the quotes database.

A3re: trusting AI
Nodari RizunNodari RizunFounder & CEO, Pürblack®
“AI, by the nature of the models, will hallucinate. And because of that, you need something which will create guardrails to ensure that there are no hallucinations, that you can trust your data.”
C9re: one source of truth
Mark SimmonsMark SimmonsCMO, Pürblack®
“We had six or seven different channels and no single source of truth — it was almost impossible, a lot of guesswork.”
E7re: getting time back
Nodari RizunNodari RizunFounder & CEO, Pürblack®
“We regained time. And time is the one resource that never comes back.”

Recent updates

Declare your first relationship

Open a Data Mart's Data Setup, click Join Data Mart, pair the keys, then tick a joined field in your next report.

Get started free

Joinable Data Marts