- Your source table has rows shaped like
entity_id | attribute_name | attribute_value, and not every entity has a row for every attribute name - You want to pivot attribute names into columns in an Omni workbook without missing rows collapsing silently
- You need a dynamic filter that scopes the query to a subset of data (for example, by a parent ID) and populates its dropdown from the database
Understanding the pattern
If your data looks like this:| entity_id | attribute_name | attribute_value |
|---|---|---|
| abc | Evidence A | Pass |
| abc | Evidence C | Fail |
| xyz | Evidence B | Pass |
| entity_id | Evidence A | Evidence B | Evidence C |
|---|---|---|---|
| abc | Pass | NULL | Fail |
| xyz | NULL | Pass | NULL |
The
fill_fields query view parameter solves a related but different problem. It fills missing values from an enumerated or date series. The cross-join approach here is for cases where both the entities and attributes are dynamic and sourced from the data itself.Requirements
To follow the steps in this guide, you’ll need:- Modeler or Connection Admin permissions on the model
-
The fully qualified path to your table (
DATABASE.SCHEMA.TABLE_NAME) -
A table with sparse key-value rows
This guide uses Snowflake to walk through examples. If using a different database, you may need to adjust the SQL to your database’s syntax.
Building the query view
Confirm the table path
Before you start working in Omni, confirm the fully qualified path to your table in Snowflake. If you’re unsure, run the following in Snowflake:Then confirm the exact database and schema:Your full table path will be:
DATABASE.SCHEMA.TABLE_NAMECreate the query view file
Query views can be created two ways in Omni: through the model IDE (recommended), or from a workbook.
- In the IDE (recommended)
- In the workbook
- Open the Omni model IDE.
- Create a file named
your_query_view.query.view(the.query.viewextension is required). - Paste the YAML from the next section into the file.
- Click Save.
Add the YAML template
Paste the following template into your query view file. Every value in
ALL_CAPS is a placeholder you’ll replace with a real value in the next step — except CREATED_AT, which is an optional column you can rename or remove (see the inline comment in the template).The placeholder table in the next step covers all substitutions. For example, if your scoping column is
ACCOUNT_ID, replace every instance of SCOPE_COLUMN with ACCOUNT_ID and rename scope_id_dim to account_id_dim everywhere it appears — including in suggest_from_field.your_query_view.query.view
Setting a default filter value is important. Without one, the cross-join CTEs will scan the entire source table on first load.
Replace placeholders in YAML
Replace each placeholder in the YAML using the table below:
Once all placeholders are replaced, your query view is ready to test.
| Placeholder | Replace with | Example |
|---|---|---|
your_query_view | The name of the query view file (without .query.view) | my_pivot_view |
DATABASE.SCHEMA.YOUR_TABLE | The fully qualified Snowflake table path | ANALYTICS.PROD.FACT_EVENTS |
ENTITY_ID_COLUMN | The column that identifies each unique entity (the rows in your pivot) | PRODUCT_ID |
ATTRIBUTE_NAME_COLUMN | The column whose distinct values become the pivot column headers | METRIC_NAME |
ATTRIBUTE_VALUE_COLUMN | The column containing the values to show in each pivot cell | METRIC_VALUE |
SCOPE_COLUMN | The column used to filter the data down to a relevant subset | ACCOUNT_ID |
CREATED_AT | Optional. The timestamp column to expose as a date dimension - remove if not needed. | EVENT_CREATED_AT |
scope_id_dim | Rename to match your scope column, keeping the _dim suffix | account_id_dim |
your_query_view.scope_id_dim (in suggest_from_field) | Update to match your renamed scope_id_dim value | my_pivot_view.account_id_dim |
your-default-value-here | The default value to pre-populate the scope filter | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
Enable pivoting in the workbook
Omni requires at least one measure on a query to enable pivoting, which is why this view defines Once the query view is saved and the model is valid:
attribute_value as a max measure.This pattern assumes at most one value per entity + attribute (+ scope) combination. If your source has multiple rows for the same combination, the
max measure returns only the highest value lexically and drops the others. De-duplicate upstream or change the aggregation if that isn’t what you want.- Open a workbook and select your query view as the data source.
- Add Entity ID as a dimension.
- Add Attribute Value (Aggregated) as a measure.
- Right-click Attribute Name in the field browser and select Pivot.
NULL shown where no value existed.To change the scope (for example, to view a different parent ID), apply the Scope Filter filter-only field that appears in the field browser under this view’s filters.Next steps
- Query view parameters — Full reference for query view syntax and options
- Templated filters — How filter templating works in Omni SQL
- Promoting model changes — How to move changes from a draft to the shared model

