documentation/cookbook/integrations/grafana/variable-dropdown.md
Create Grafana variable dropdowns where the displayed label differs from the value used in queries. This is useful when you want to show user-friendly names in the dropdown while using different values (like IDs, prices, or technical identifiers) in your actual SQL queries.
You want a Grafana variable dropdown that:
"BTC-USDT", "ETH-USDT", "SOL-USDT"37779.62, 2615.54, 98.23) or IDsFor example, with this query result:
| symbol | price |
|---|---|
| BTC-USDT | 37779.62 |
| ETH-USDT | 2615.54 |
| SOL-USDT | 98.23 |
You want the dropdown to show "BTC-USDT" but use 37779.62 in your queries.
When using the QuestDB data source plugin, you can use Grafana's regex variable filters to parse a concatenated string into separate text and value fields.
First, combine both columns into a single string with a separator that doesn't appear in your data:
WITH t AS (
SELECT symbol, first(price) as price
FROM trades
WHERE symbol LIKE '%BTC%'
)
SELECT concat(symbol, '#', price) FROM t;
Query results:
DOGE-BTC#0.00000204
ETH-BTC#0.05551
BTC-USDT#37779.62
SOL-BTC#0.0015282
MATIC-BTC#0.00002074
BTC-USDC#60511.1
Each row is now a single string with symbol and price separated by #.
In your Grafana variable configuration:
Query:
WITH t AS (
SELECT symbol, first(price) as price
FROM trades
WHERE symbol LIKE '%BTC%'
)
SELECT concat(symbol, '#', price) FROM t;
Regex Filter:
/(?<text>[^#]+)#(?<value>.*)/
This regex pattern:
(?<text>[^#]+): Captures everything before # into the text group (the display label)#: Matches the separator(?<value>.*): Captures everything after # into the value group (the query value)Now you can reference the variable in your dashboard queries:
SELECT timestamp, price
FROM trades
WHERE price = $your_variable_name
AND timestamp >= $__fromTime
AND timestamp <= $__toTime;
When a user selects "BTC-USDT" from the dropdown, Grafana will substitute the corresponding price value (37779.62) into the query.
Grafana's regex filter with named capture groups enables the separation:
(?<text>...) and (?<value>...) tell Grafana which parts to usetext group: Becomes the visible label in the dropdownvalue group: Becomes the interpolated value in queries/(?<text>[^#]+)#(?<value>.*)/
/: Regex delimiters(?<text>...): Named capture group called "text"[^#]+: One or more characters that are NOT # (greedy match)#: Literal separator character(?<value>.*): Named capture group called "value".*: Zero or more characters of any type (captures rest of string)Pick a separator that never appears in your data:
Good separators:
# - Uncommon in most data| - Clear visual separator:: - Two characters, unlikely to appear~ - Rarely used in trading symbols or prices^^^ - Multi-character separator for extra safetyBad separators:
- - Common in trading pairs (BTC-USDT). - Common in decimal numbers, - Common in CSV-like dataIf you need more than two fields, use additional separators:
SELECT concat(symbol, '#', price, '#', volume) FROM trades;
/(?<text>[^#]+)#(?<value>[^#]+)#(?<extra>.*)/
Now you have three captured groups, though Grafana's variable system typically only uses text and value.
Common pattern for entity selection:
SELECT concat(name, '#', id) FROM users;
/(?<text>[^#]+)#(?<value>\d+)/
Output in dropdown: User sees "John Doe", query uses 42.
If your data contains regex special characters, escape them in the pattern:
-- If data contains parentheses
SELECT concat(name, ' (', id, ')', '#', id) FROM users;
-- Result: "John Doe (42)#42"
/(?<text>.*?)#(?<value>\d+)/
If using the PostgreSQL data source (instead of the QuestDB plugin), you can use special column aliases:
SELECT
symbol AS __text,
price AS __value
FROM trades
WHERE symbol LIKE '%BTC%';
The PostgreSQL data source recognizes __text and __value as special column names for dropdown variables.
Note: This works with the PostgreSQL data source plugin pointing to QuestDB, but NOT with the native QuestDB data source plugin.
Different filter conditions:
-- Filter by time range
WHERE timestamp IN '$yesterday'
-- Filter by multiple criteria
WHERE symbol LIKE '%USDT' AND price > 1000
-- Dynamic filter using another variable
WHERE symbol LIKE concat('%', $base_currency, '%')
Sorting the dropdown:
-- Sort alphabetically by symbol
SELECT concat(symbol, '#', price) FROM trades
ORDER BY symbol;
-- Sort by price (highest first)
SELECT concat(symbol, '#', price) FROM trades
ORDER BY price DESC;
-- Sort by volume
WITH t AS (
SELECT symbol, first(price) as price, sum(amount) as volume
FROM trades
GROUP BY symbol
)
SELECT concat(symbol, '#', price) FROM t
ORDER BY volume DESC;
Include additional context in label:
-- Show symbol and volume in the label
SELECT concat(symbol, ' (Vol: ', round(sum(amount), 2), ')', '#', first(price))
FROM trades
GROUP BY symbol;
Result: "BTC-USDT (Vol: 1234.56)#37779.62"
Dropdown shows concatenated string:
/.../ (forward slashes)(?<text>...) and (?<value>...)Variable not interpolating in queries:
$variable_name syntax in queriesRegex not matching:
Dropdown is empty:
:::tip Multi-Select Variables
This pattern works with multi-select variables too. Enable "Multi-value" in the variable configuration, and users can select multiple options. Use IN ($variable) in your queries to handle multiple selected values.
:::
:::tip Variable Preview Grafana shows a preview of what the dropdown will look like when you configure the regex filter. Use this to verify your pattern is working correctly before applying it. :::
:::info Related Documentation