Pro ยท Lesson 5 of 9
Native questions use variables, field filters, and optional clauses so a dashboard can drive SQL safely.
Sign in to save your place.
A SQL question is a letter with blanks. {{status}} is a blank the reader fills in. A field filter is a smarter blank: Metabase knows it is a real column, so it can offer a date picker or a dropdown. Double brackets around a line mean 'leave this line out if the blank is empty'.
Use the query builder when a reader should change the steps. Use a native SQL question when the logic needs a join, a window, or a warehouse function the builder does not express. Save it in a collection like any other question. It can still sit on a dashboard.
A variable is written as {{variable}}. In the variable sidebar, set the type. Text, number, and date variables are substituted as values, not as raw SQL fragments, so a reader cannot end the statement and start a new one by typing into the box. That is the point of the widget.
SELECT country, SUM(amount) AS revenue
FROM orders
WHERE status = {{status}}
AND ordered_at >= {{start_date}}
GROUP BY country
ORDER BY revenue DESCA field filter connects the widget to a real column. You write the column once and let Metabase build the predicate, including "is empty" and date ranges. The SQL names the field, and the widget decides the operator.
SELECT id, country, amount
FROM orders
WHERE {{created_at}}
[[AND country = {{country}}]]The line inside [[ ]] is omitted when Country is empty. Without those brackets, an empty widget becomes a filter for blank country, or the query fails. Use optional clauses for filters people are allowed to skip.
Snippets are reusable SQL fragments saved in Metabase. Use them for a join you repeat. Do not hide a permission check inside a snippet and assume it is security. Permissions are the admin lesson. A snippet is only text.
If you need a dynamic identifier such as a schema name, that is not a value variable. Keep identifiers in the saved SQL. Let widgets pass values only.
Variables in double curly brackets turn a SQL query into a reusable filter.
Step 1 of 3A text or number variable is replaced with whatever the reader types into the filter box.
SELECT * FROM orders WHERE city = {{city}}
Step 2 of 3A field filter is linked to a real column, so readers get Metabase's date picker and Metabase writes the condition. Do not put the column name before it.
SELECT * FROM orders WHERE {{created}}
Step 3 of 3Square brackets make part of the query optional. If the reader leaves the filter empty, the whole bracketed part is dropped.
SELECT * FROM orders WHERE true [[AND city = {{city}}]]
Save a native question with one required text variable and one optional clause. Run it with the optional filter empty, then filled. Both runs should succeed, and only the second should restrict that column.
Checked against vendor documentation in October 2026. Screens and plan names still change, so confirm the control in your own instance.