mirror of
https://github.com/apache/superset.git
synced 2026-05-08 01:15:46 +00:00
- Snapshot all four versioned docs sections at v6.1.0; master continues to serve as "Next" (lastVersion: current, banner: unreleased) so editing master keeps updating the canonical URLs - Enable the previously-disabled components plugin and version it - Rename stale "developer_portal" references to "developer_docs" across package.json scripts, manage-versions.mjs, theme files (DocVersionBadge, DocVersionBanner), DOCS_CLAUDE.md, and README.md (URL backward-compat redirect /developer_portal/* preserved) - Add admin_docs version scripts; drop dead "tutorials" plugin id from the version badge - Generalize fixVersionedImports in manage-versions.mjs to walk every section's snapshot and rewrite ../../src/ and ../../data/ imports, catching admin_docs and components files that previous version cuts would have broken - Remove orphan files: developer_portal_versions.json, tutorials_versions.json, and stray empty versions.json files inside components/ and developer_docs/ content directories
275 lines
6.9 KiB
Plaintext
275 lines
6.9 KiB
Plaintext
---
|
|
title: SQL Templating
|
|
sidebar_position: 4
|
|
description: Use Jinja templates in SQL Lab and virtual datasets to create dynamic queries
|
|
keywords: [sql templating, jinja, sql lab, virtual datasets, dynamic queries]
|
|
---
|
|
|
|
{/*
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
*/}
|
|
|
|
# SQL Templating
|
|
|
|
Superset supports [Jinja templating](https://jinja.palletsprojects.com/) in SQL Lab queries and virtual datasets. This allows you to write dynamic SQL that responds to filters, user context, and URL parameters.
|
|
|
|
:::note
|
|
SQL templating must be enabled by your administrator via the `ENABLE_TEMPLATE_PROCESSING` feature flag.
|
|
For advanced configuration options, see the [SQL Templating Configuration Guide](/admin-docs/configuration/sql-templating).
|
|
:::
|
|
|
|
## Using Jinja in Calculated Columns
|
|
|
|
Jinja template macros are available in calculated column expressions in the dataset editor — not just in SQL Lab queries and virtual datasets. This allows column expressions to reference the current user or dynamic context.
|
|
|
|
**Example: User-scoped calculated column**
|
|
|
|
```sql
|
|
CASE WHEN sales_rep = '{{ current_username() }}' THEN amount ELSE 0 END
|
|
```
|
|
|
|
**Example: Conditional display based on role**
|
|
|
|
Because `current_user_roles()` returns a Python list, test role membership with a Jinja
|
|
conditional at template time rather than matching against the list's string representation:
|
|
|
|
```sql
|
|
{% if 'Finance' in current_user_roles() %}revenue{% else %}NULL{% endif %} AS finance_revenue
|
|
```
|
|
|
|
:::note
|
|
The `ENABLE_TEMPLATE_PROCESSING` feature flag must be enabled by your administrator for Jinja in calculated columns to work.
|
|
:::
|
|
|
|
## Basic Usage
|
|
|
|
Jinja templates use double curly braces `{{ }}` for expressions and `{% %}` for logic blocks.
|
|
|
|
### Using Parameters
|
|
|
|
You can define parameters in SQL Lab via the **Parameters** menu as JSON:
|
|
|
|
```json
|
|
{
|
|
"my_table": "sales",
|
|
"start_date": "2024-01-01"
|
|
}
|
|
```
|
|
|
|
Then reference them in your query:
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM {{ my_table }}
|
|
WHERE order_date >= '{{ start_date }}'
|
|
```
|
|
|
|
### Conditional Logic
|
|
|
|
Use Jinja's logic blocks for conditional SQL:
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM orders
|
|
WHERE 1 = 1
|
|
{% if start_date %}
|
|
AND order_date >= '{{ start_date }}'
|
|
{% endif %}
|
|
{% if end_date %}
|
|
AND order_date < '{{ end_date }}'
|
|
{% endif %}
|
|
```
|
|
|
|
## Available Macros
|
|
|
|
Superset provides built-in macros for common use cases.
|
|
|
|
### User Context
|
|
|
|
| Macro | Description |
|
|
|-------|-------------|
|
|
| `{{ current_username() }}` | Returns the logged-in user's username |
|
|
| `{{ current_user_id() }}` | Returns the logged-in user's account ID |
|
|
| `{{ current_user_email() }}` | Returns the logged-in user's email |
|
|
| `{{ current_user_roles() }}` | Returns an array of the user's roles |
|
|
|
|
**Example: Row-level filtering by user**
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM sales_data
|
|
WHERE sales_rep = '{{ current_username() }}'
|
|
```
|
|
|
|
**Example: Role-based access**
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM users
|
|
WHERE role IN {{ current_user_roles()|where_in }}
|
|
```
|
|
|
|
### Filter Values
|
|
|
|
Access dashboard and chart filter values in your queries:
|
|
|
|
| Macro | Description |
|
|
|-------|-------------|
|
|
| `{{ filter_values('column') }}` | Returns filter values as a list |
|
|
| `{{ get_filters('column') }}` | Returns filters with operators |
|
|
|
|
**Example: Using filter values**
|
|
|
|
```sql
|
|
SELECT product, SUM(revenue) as total
|
|
FROM sales
|
|
WHERE region IN {{ filter_values('region')|where_in }}
|
|
GROUP BY product
|
|
```
|
|
|
|
The `where_in` filter converts the list to SQL format: `('value1', 'value2', 'value3')`
|
|
|
|
### Time Filters
|
|
|
|
For charts with time range filters:
|
|
|
|
| Macro | Description |
|
|
|-------|-------------|
|
|
| `{{ get_time_filter('column') }}` | Returns time filter with `from_expr` and `to_expr` |
|
|
|
|
**Example: Time-filtered virtual dataset**
|
|
|
|
```sql
|
|
{% set time_filter = get_time_filter("order_date", default="Last 7 days") %}
|
|
SELECT *
|
|
FROM orders
|
|
WHERE order_date >= {{ time_filter.from_expr }}
|
|
AND order_date < {{ time_filter.to_expr }}
|
|
```
|
|
|
|
### URL Parameters
|
|
|
|
Pass custom values via URL query strings:
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM orders
|
|
WHERE country = '{{ url_param('country') }}'
|
|
```
|
|
|
|
Access via: `superset.example.com/sqllab?country=US`
|
|
|
|
### Reusing Dataset Definitions
|
|
|
|
Query existing datasets by ID:
|
|
|
|
```sql
|
|
-- Query a dataset (ID 42) as a table
|
|
SELECT * FROM {{ dataset(42) }} LIMIT 100
|
|
|
|
-- Include computed metrics
|
|
SELECT * FROM {{ dataset(42, include_metrics=True) }}
|
|
```
|
|
|
|
Reuse metric definitions across queries:
|
|
|
|
```sql
|
|
SELECT
|
|
category,
|
|
{{ metric('total_revenue') }} as revenue
|
|
FROM sales
|
|
GROUP BY category
|
|
```
|
|
|
|
## Testing Templates in SQL Lab
|
|
|
|
Some variables like `from_dttm` and `filter_values()` only work when filters are applied from dashboards or charts. To test in SQL Lab:
|
|
|
|
**Option 1: Use defaults**
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM orders
|
|
WHERE date >= '{{ from_dttm | default("2024-01-01", true) }}'
|
|
```
|
|
|
|
**Option 2: Set test parameters**
|
|
|
|
Add to the Parameters menu:
|
|
|
|
```json
|
|
{
|
|
"_filters": [
|
|
{"col": "region", "op": "IN", "val": ["US", "EU"]}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Option 3: Use `{% set %}`**
|
|
|
|
```sql
|
|
{% set start_date = "2024-01-01" %}
|
|
SELECT * FROM orders WHERE date >= '{{ start_date }}'
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Dynamic Table Selection
|
|
|
|
```sql
|
|
{% set table_name = url_param('table') or 'default_table' %}
|
|
SELECT * FROM {{ table_name }}
|
|
```
|
|
|
|
### User-Specific Data Access
|
|
|
|
```sql
|
|
SELECT *
|
|
FROM sensitive_data
|
|
WHERE department IN (
|
|
SELECT department
|
|
FROM user_permissions
|
|
WHERE username = '{{ current_username() }}'
|
|
)
|
|
```
|
|
|
|
### Time-Based Partitioning
|
|
|
|
```sql
|
|
{% set time_filter = get_time_filter("event_date", remove_filter=True) %}
|
|
SELECT *
|
|
FROM events
|
|
WHERE event_date >= {{ time_filter.from_expr }}
|
|
AND event_date < {{ time_filter.to_expr }}
|
|
```
|
|
|
|
Using `remove_filter=True` applies the filter in the inner query for better performance.
|
|
|
|
## Tips
|
|
|
|
- Use `|where_in` filter to convert lists to SQL `IN` clauses
|
|
- Use `|tojson` to serialize arrays as JSON strings
|
|
- Test queries with explicit parameter values before relying on filter context
|
|
- For complex templating needs, ask your administrator about custom Jinja macros
|
|
- **Format SQL is Jinja-aware**: The "Format SQL" button in SQL Lab correctly preserves `{{ }}` and `{% %}` template syntax and applies your selected database's SQL dialect when formatting.
|
|
|
|
:::resources
|
|
- [Admin Guide: SQL Templating Configuration](/admin-docs/configuration/sql-templating)
|
|
- [Blog: Intro to Jinja Templating in Apache Superset](https://preset.io/blog/intro-jinja-templating-apache-superset/)
|
|
:::
|