Jinja templating

Introduction

Jinja is a templating library written in Python, traditionally used for rendering HTML web pages. However, the jinja library can be used to generate any type of text, and in Count you can use it in SQL cells to write queries.

Jinja expressions are enclosed in curly braces and support a subset of Python syntax, so compiling {{ 1 + 1 }} (for example) would generate 2.

How jinja templating works

When you include Jinja delimiter tags in a SQL cell (i.e. any of {{, }}, {%, %}, {#, #}), Count will attempt to compile the cell text as a jinja template before executing the cell. To view the compiled SQL that is actually executed, click the Show compiled SQL button in the design bar:

Jinja templates are local to each cell, so variable and macro definitions are not shared between cells.

When writing templates in SQL cells, all jinja functionality is available including:

For loops

Loop over any Python iterable and execute the expression in the body of the loop:

If expressions

Return different text depending on the result of some boolean value:

Set expressions

Declare a local variable and use it in subsequent expressions:

Macros

Define a function that can be called from subsequent expressions:

Additional functionality provided by Count

Count provides several helper functions in addition to the standard Jinja functionality. Read more about these helper functions from the documentation available through the cell autocomplete:

ref

The ref macro formats strings as SQL identifiers, adding delimiter characters and escaping as required by your database:

If the source for this cell has a dbt connection, then the ref() macro can also reference models.

cells

The cells variable can be used to access the value of control cells without the requirement to use subqueries or joins - the control cell value is compiled directly into the SQL query:

Control cell values are formatted as literals by default.

To access the string value of a control cell more generally, use the Jinja string() filter, for example:

{% if cells.b | raw | string() == 'some text' %}
...

literal / identifier / raw filters

These filters are provided by Count to format control cell values appropriately for your database:

It is currently only possible to format the values of control cells using these filters.

Additional functionality for dbt

If the current source has a dbt integration connected, then the available functionality in jinja is increased to include:

  • All built-in dbt APIs and macros

  • Any macros defined in your dbt project

Explore these additional options using autocomplete while focussed within a Jinja block.

When to use Jinja

When writing queries, it is recommended to use plain SQL as much as possible for maximum portability and clarity. However, there are some cases where using Jinja is preferable or required.

Avoiding subqueries

Some databases restrict the use of too many subqueries, which can make it difficult to use control cells effectively. In this case it is possible to remove subqueries by switching to Jinja. For example, if your SQL looks like:

select * from table where column = (select value from control_cell)

then change it to:

select * from table where column = {{ cells.control_cell }}

If your control cell is a multiple select, note that the compiled SQL does not contain any parentheses, so the SQL you write may look like:

select * from table where column in ( {{ cells.control_cell }} )

Dynamic query structure

Some manipulations are impossible in SQL, such as dynamically changing the number of selected columns or the tables in the FROM clause. In these cases it is possible to use jinja templating instead:

Last updated