Skip to main content
This guide helps Tableau users understand how to model their analytics in Honeydew.If you are not familiar with Tableau, head over to the introduction instead.

Introduction

Honeydew is a standalone semantic layer. It sits between your data warehouse and the tools that consume it: Tableau, Power BI, Excel, SQL clients, AI agents, notebooks. Tableau is one of those tools. The job of the semantic layer is to define the building blocks once and use them everywhere. Semantics include the following concepts:
  1. How business entities (such as “customer”) are mapped to data sources (which tables to read from)
  2. How data tables are related (which joins to use)
  3. How metrics are calculated (which aggregations to perform)
  4. Metadata (such as descriptions, display names, formatting) associated with presenting those objects to business users.
If you build dashboards in Tableau, you already work with all four: you map fields to tables in a data source, define relationships, write calculated fields and LODs, and add display formatting. The Honeydew equivalents share the same intent, just centralized so multiple workbooks, dashboards, and tools can reuse them. When you connect Tableau to Honeydew, Tableau queries a virtual table instead of querying raw warehouse tables directly. The logic that today lives in your Tableau workbooks (calculated fields, LOD expressions, data blending) moves into Honeydew where it can be reused across dashboards and tools.
The goal is not to replicate Tableau logic 1:1 in Honeydew. Instead, you define the building blocks (entities, relationships, metrics) once, and Tableau consumes them through a live connection.

Visual to declarative

In Tableau you think visually: drag a dimension to Rows, drop a measure on Columns, add a filter to the shelf, write an LOD expression to change the grain. In Honeydew you think declaratively: define entities, connect them with relationships, write metrics that describe what to calculate. The how - which joins, which GROUP BY, which filters - is resolved automatically at query time.

Data Sources and Entities

A Tableau data source connects to one or more warehouse tables, defines joins between them, and exposes dimensions and measures for worksheets. In Honeydew, each table becomes an Entity. Joins between tables become Relationships defined once and reused across all queries.
A Tableau Published Data Source maps to a Honeydew Domain - a curated subset of the model tailored to a specific business area.

Custom SQL in data sources

Tableau allows a data source to use Custom SQL. An entity in Honeydew can also be backed by a custom SQL query instead of a single table - see source data.

Data blending

In Tableau, data blending links fields across separate physical data sources using a common dimension. Honeydew operates on a single physical source (a cloud data warehouse), so the equivalent depends on what was being blended. When the blended data lives in the same warehouse and just needs to be linked through a common dimension, use a relationship, often backed by a shared dimension. When the data lives in a different warehouse, database, or system, there is no Honeydew equivalent. The cross-source join has to happen either in the warehouse itself (through federation or external tables) or in the dashboard layer.

Relationships and Joins

Tableau’s data model supports relationships (logical layer) and joins (physical layer). Honeydew relationships combine both concepts:
  • Join fields: Honeydew supports composite keys (multiple fields) and calculated attributes as join keys - no need to create concatenated key fields.
  • Join type: LEFT, INNER, RIGHT, or FULL OUTER.
  • Cardinality: one-to-many and many-to-one work directly. Many-to-many requires a connecting table.
  • Cross-filtering: controls whether filters on one entity affect another. The default is bidirectional, matching how Tableau’s logical layer behaves.
In Tableau’s logical layer, tables are related but not joined until needed. Honeydew works similarly - joins are defined as relationships and only executed when a query requires fields from both entities.

Calculated Fields → Attributes

A Tableau calculated field that produces a dimension (string, date, boolean, etc.) maps to a calculated attribute in Honeydew.

Basic calculated fields

Tableau:
Honeydew calculated attribute in the customer entity:
In Tableau, a calculated field can reference any field in the data source after a join. In Honeydew, relationships are resolved automatically. Reference any related entity directly:
No need to specify how to join - Honeydew resolves the path from sales to product through defined relationships.

Groups and Sets

Tableau Groups let you manually bucket dimension values. Tableau Sets create binary in/out classifications based on conditions. Both map to calculated attributes in Honeydew: Tableau Group:
Tableau Set (high-value customers above a threshold):
The is_high_value attribute uses a metric (sales.total_sales) in its definition. Calculated attributes that reference metrics are evaluated at the entity’s grain - here, per customer.

Calculated Fields → Metrics

A Tableau calculated field that produces a measure (an aggregation) maps to a metric in Honeydew.

Basic aggregations

Tableau:
Honeydew:
Tableau:
Honeydew:
customer.count is the entity count metric of the customer entity. Honeydew resolves the relationship between sales and customer automatically, giving a distinct count of customers per the query’s grouping.COUNT(DISTINCT sales.customer_id) would also work, but referencing the entity count is the recommended approach.

Common aggregation mapping

The SQL syntax depends on the connected data warehouse (Snowflake, Databricks, etc.). The examples below use Snowflake syntax.

Derived metrics

Metrics in Honeydew can reference other metrics:
Define each building block once and reuse it. The profit and margin metrics do not repeat the aggregation logic - they compose existing metrics.

Filters

Tableau has multiple layers of filters that execute in a specific order: extract filters, data source filters, context filters, dimension filters, measure filters. Honeydew domains have two types of filters:
  • Source filters apply directly on source tables before any calculation or join. Used for performance optimization (e.g., partition pruning) and data deduplication.
  • Semantic filters apply to every query in a domain, after joins are resolved. Used for governance and access control (e.g., tenant filtering). A semantic filter may introduce additional joins to enforce its condition.
In addition, user query filters are applied through SQL:
  • WHERE filters on attributes (dimensions)
  • HAVING filters on metrics (measures)
See order of filtering for the full computation order.
Semantic filters always apply to every query in a domain - they cannot be toggled by the user. For filters that should apply by default but can be overridden by user selections, see conditional filtering.

Adding filters to a metric

Tableau does not have a first-class “filtered measure” construct. To make a measure that always filters to a subset of rows - regardless of what the user selects in the view - you fold the filter into the aggregate using an IF expression. Non-matching rows return NULL and SUM ignores them. Tableau:
Honeydew has filtered metrics as a first-class concept: a FILTER (WHERE ...) qualifier attached to a metric expression. The filter lives next to the metric, not inside it.
The qualifier also works on derived metrics that wrap an existing metric:
The FILTER (WHERE ...) qualifier adds a filter to the metric without affecting the rest of the query. All user filters still apply on top.

LOD Expressions

LOD (Level of Detail) expressions are one of the most common Tableau constructs that need to be rethought in Honeydew. In Tableau, LODs let you control the granularity of a calculation independently from the level of detail in the view. In Honeydew, there are two ways to control granularity, and the choice depends on how the calculation should interact with user filters: This distinction is important when translating LOD expressions.

FIXED

A FIXED LOD computes an aggregation at a specific grain. In Tableau, FIXED ignores dimension filters but respects context filters and data source filters.
For the full reference of how each Tableau filter type interacts with LOD expressions, see Tableau’s Filters and Level of Detail Expressions.
Tableau:
Honeydew - as a calculated attribute (ignores user filters):
A calculated attribute that uses an aggregation automatically groups to the entity’s primary key. Since calculated attributes are computed before user filters, this closely matches the Tableau FIXED behavior of ignoring dimension filters. Honeydew - as a metric with fixed grouping (respects user filters):
The calculated attribute and the metric with GROUP BY both fix the grain to customer, but they differ in how they handle user filters:
  • customer.lifetime_sales (attribute) always returns the same value regardless of user filters.
  • sales.sales_per_customer (metric) respects user WHERE filters - if a user filters to 2024 data, the metric returns sales per customer in 2024 only.
Choose based on whether the calculation should be affected by user filters or not.

FIXED with multiple dimensions

Tableau:
Honeydew:

INCLUDE

An INCLUDE LOD adds dimensions to the view’s current grain. Tableau:
Honeydew:
GROUP BY (*, field) means “the user’s current grouping plus this additional field.” This is the Honeydew equivalent of Tableau’s INCLUDE.
This is the foundation of multi-level aggregations. Wrap sales.orders_per_customer in an outer aggregate to get an “average orders per customer” metric:
The inner metric fixes the per-customer grain; the outer AVG averages across whatever the user breaks the result down by - region, segment, month, or all of them at once.

EXCLUDE

An EXCLUDE LOD removes dimensions from the view’s current grain. Tableau:
This removes the month dimension from the aggregation, giving a coarser total while the view still shows monthly detail. Honeydew:
GROUP BY (NOT field) means “the user’s current grouping minus this field.” This is the Honeydew equivalent of Tableau’s EXCLUDE.

Percent of total

A very common Tableau pattern is percent of total using LODs: Tableau:
Or using a table calculation:
Honeydew:
GROUP BY () removes all grouping, giving the grand total. The numerator uses the query’s grouping.

Percent of parent (nested LOD pattern)

Tableau:
Honeydew:

LOD summary

Table Calculations

Tableau table calculations operate on the result set after aggregation - running totals, ranks, moving averages, percent differences. They depend on the sort order and partitioning of the view. Honeydew handles these patterns differently depending on the calculation type.

Running total / cumulative sum

Tableau:
Honeydew - as a calculated attribute with a window function:
Window functions in calculated attributes operate at the entity row level, not at the query result level. For cumulative sums over a query result, use Tableau’s built-in table calculation on a Honeydew metric.

Rank

Tableau:
Ranking over a query result is best done in Tableau on top of a Honeydew metric. Honeydew provides the aggregated values; Tableau applies the rank. For ranking at the entity level (e.g., rank orders by price within a customer), use a window function in a calculated attribute:

Percent difference

Tableau:
For period-over-period comparisons, Honeydew offers time-based metrics that compute offsets like previous period values without relying on result-set ordering.
Table calculations that depend on the visual layout (sort order, partition) are best left in Tableau. Honeydew provides the well-defined aggregated metrics; Tableau applies layout-dependent calculations on top.

Parameters

Tableau parameters let users select a value at runtime to control filters, reference lines, or calculation logic. Honeydew supports two approaches:

BI parameters

Honeydew can pass through Tableau parameter values using BI parameters. This lets you build metrics whose behavior changes based on user selection.

Conditional filtering

For parameters that switch between dimensions or control which filter to apply, conditional filtering in Honeydew provides GET_FIELD_SELECTION():
This is useful for building dynamic titles, conditional logic, or metrics that behave differently based on user filter selections.

Other Patterns

Threshold filtering

Tableau lets you create filters based on measure values (e.g., only show products with more than $1,000 in sales). In Tableau, the threshold is often controlled by a parameter. In Honeydew, use a metric in a filter with conditional filtering to make the threshold dynamic:
The threshold defaults to 1,000 but the user can change it by filtering dim_threshold.min_sales to a different value - similar to how a Tableau parameter works.

Top N filtering

Tableau lets you filter a dimension to show only the top N items by a measure (e.g., top 10 products by sales). Top N filtering depends on the query’s grouping and sort order, so it should be applied in Tableau using a Tableau parameter and a Top N filter on a Honeydew metric. Honeydew provides the aggregated metric values; Tableau handles the ranking and filtering.

Period-over-period comparison

Tableau:
Honeydew provides time-based metrics for period offsets. This is the year-over-year comparison:
Use time-based metrics when the comparison must be defined centrally so every consumer sees the same year-over-year (or other-period) definition. For comparisons that only matter inside one workbook, it is often simpler to keep them in Tableau as table calculations or part of the visual presentation.

Next Steps