Skip to content

SQL nodes

SQL nodes query your data source with explicit SQL code. They take no input nodes, but they can reference other nodes on the canvas by name. Create a SQL node by clicking on the toolbar. Or, select an existing node and click New SQL node on the new node toolbar floating to the right.

A SQL node

Configuration

The base query is configured by writing a SELECT statement to be run against your data source in its dialect. The statement can refer to nodes on the page as if they were database tables.

That base query can be refined by the standard controls shared by all table nodes.

SQL equivalent

If you clicked “Copy SQL” in the node menu of the node pictured above, you’d get:

sql
WITH
  "RECENT_PURCHASES" AS (…),
  "SQL_3_sql" AS (
    SELECT *
    FROM "RECENT_PURCHASES"
    JOIN SURVEY
      ON SURVEY.RESPONSE_ID
      = RECENT_PURCHASES.SURVEY_ID
    )
SELECT
  "ORDER_DATE",
  "PRICE_PER_UNIT",
  "QUANTITY",

FROM "SQL_3_sql"

In the real version, the first would show the SQL code for the referenced node named RECENT_PURCHASES. The other referenced table, SURVEY, is in the database, so it does not get expanded into a CTE. This means the “Copy SQL” code is self-contained and portable; it could run directly on the data source.

The second would materialize all displayed columns of the table.

Examples

Query your database

SQL offers more flexibility than other canvas nodes, allowing for more complex filtering:

sql
SELECT * FROM USERS WHERE name LIKE 'Chloe%'

The query must be a valid SELECT statement. Any other statement (such as INSERT, PRAGMA, COPY, or CREATE) results in a syntax error.

You can also address the table by its full qualified name:

sql
SELECT * FROM "database"."schema"."table"

Query your canvas nodes

You can reference any node on your canvas by name as if it were a table in the source database, including joining database tables and canvas nodes. For example, you could query a chart node named SELECTED_USERS:

sql
SELECT * FROM SELECTED_USERS

The referenced node is transformed into a common table expression (CTE), as you can see by clicking “Copy SQL”. The CTE includes filters and brushes applied to upstream nodes. As you brush a chart upstream, the CTE updates live.

INFO

A node takes priority over a table with the same name. You cannot create a node with the same name as an existing database table, but the database schema could change to conflict after the node was created. You can rename the conflicting node on the canvas, or qualify the database table (FROM "database"."schema"."table") to disambiguate.

Create a table of literal values

You can supplement your data source with a small table of literal values:

sql
SELECT * FROM (VALUES
  ('Alice', '2023-01-02'::Date, 30),
  ('Bob', '2024-06-13', 42),
  ('Chloe', '2025-02-04', 76),
  ('Donna', '2025-11-22', 14)
) AS USERS (name, created, age)

Use functions specific to your data source’s dialect

The SQL node uses the source database’s SQL dialect. For example, to compute quantiles in a Snowflake database, you can call APPROX_PERCENTILE:

sql
SELECT APPROX_PERCENTILE(body_mass_g, 0.95) FROM penguins

For a similar operation, DuckDB uses APPROX_QUANTILE:

sql
SELECT APPROX_QUANTILE(body_mass_g, 0.95) FROM penguins

DuckDB: Load data from a URL

If your data source is DuckDB, you can load data directly from a CSV or a JSON:

sql
SELECT * FROM READ_CSV(
  'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.csv'
  , ignore_errors = true)

Or, in the short-form syntax:

sql
SELECT * FROM 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.csv'

Generate random values

This query generates a normal distribution with the Box-Muller transform:

sql
WITH pairs AS (
  SELECT random() AS u1, random() AS u2
  FROM range(1000)
)
SELECT sqrt(-2.0 * ln(u1)) * cos(2.0 * pi() * u2) AS r
FROM pairs