Via Kondado: KSQL Reference

KSQL is Kondado's query language. It uses a JSON syntax that lets you filter, group, sort, and transform your data in a simple and secure way.

ℹ️ Beta: KSQL queries are available in beta mode.

Basic structure

A KSQL query is a JSON object with the following fields:

FieldRequiredDescription
dest_collection_idYesYour destination collection identifier
table_nameYesName of the table to query
columnsYesList of columns to return
column_aggregationsNoAggregation type per column (e.g., "sum", "avg", "none")
dimensionsNoGrouping columns (equivalent to GROUP BY)
where_conditionsNoFilter conditions
order_byNoResult sorting
limitNoMaximum number of records (max: 1,000)
customColumnsNoCalculated columns with custom expressions
column_transformationsNoTransformations applied to columns
joinsNoJoin with other tables
unionNoArray of queries to combine with UNION ALL (replaces other fields)

Minimal example

{
  "dest_collection_id": 12345,
  "table_name": "sales",
  "columns": ["product", "amount", "date"]
}

Filters (where_conditions)

Filters are defined as a list of conditions. All conditions are combined with AND.

"where_conditions": [
  {"column": "status", "operator": "=", "value": "active"},
  {"column": "amount", "operator": ">", "value": 100}
]

Comparison operators

OperatorDescriptionExample value
=Equal to"active"
!=Not equal to"cancelled"
>Greater than100
<Less than50
>=Greater than or equal100
<=Less than or equal200

Set operators

OperatorDescriptionExample value
INIs in the list["US", "UK", "CA"]
NOT INIs not in the list["cancelled", "expired"]

Text operators

OperatorDescriptionExample value
LIKEMatches pattern (use % as wildcard)"%kondado%"
NOT LIKEDoes not match pattern"%test%"
STARTS_WITHStarts with"BR"
ENDS_WITHEnds with".com"
CONTAINSContains the text"kondado"
NOT_CONTAINSDoes not contain"test"

Null operators

OperatorDescription
IS NULLIs null
IS NOT NULLIs not null

Range operator

OperatorDescriptionExample value
BETWEENIs between two values[100, 500]

Relative date operators

These operators make date filtering easy without manual date calculations:

OperatorDescription
LAST_N_DAYSLast N days
NEXT_N_DAYSNext N days
LAST_N_HOURSLast N hours
LAST_N_MINUTESLast N minutes
THIS_WEEKCurrent week
LAST_WEEKPrevious week
THIS_MONTHCurrent month
LAST_MONTHPrevious month
THIS_QUARTERCurrent quarter
LAST_QUARTERPrevious quarter
THIS_YEARCurrent year
LAST_YEARPrevious year

Example:

{"column": "created_at", "operator": "LAST_N_DAYS", "value": 7}

Aggregations

To calculate metrics on your data, use column_aggregations together with dimensions.

The column_aggregations field is a list with the same length as columns. Each position defines the aggregation for the corresponding column. Use "none" for columns without aggregation (these should be listed in dimensions).

{
  "table_name": "orders",
  "columns": ["category", "revenue", "quantity"],
  "column_aggregations": ["none", "sum", "count"],
  "dimensions": ["category"]
}

Available aggregation functions

FunctionDescription
noneNo aggregation (grouping column)
sumSum of values
avgAverage of values
countRecord count
count_distinctCount of unique values
minMinimum value
maxMaximum value
stddevStandard deviation
varianceVariance

Sorting (order_by)

"order_by": [
  {"column": "revenue", "direction": "desc"},
  {"column": "name", "direction": "asc"}
]

Calculated columns (customColumns)

Create derived columns using expressions:

"customColumns": [
  {"name": "profit", "expression": "revenue - cost"},
  {"name": "margin", "expression": "(revenue - cost) / revenue * 100"}
]

Calculated columns can be used in columns, where_conditions, order_by, and dimensions, just like any other column.

Functions available in expressions

Math: ABS, CEIL, FLOOR, ROUND, TRUNCATE, MOD, SQRT, POWER, EXP, LOG, LN, SIGN

Text: UPPER, LOWER, TRIM, LTRIM, RTRIM, SUBSTR, SUBSTRING, LENGTH, REPLACE, CONCAT, SPLIT_PART, LEFT, RIGHT, LPAD, RPAD, REVERSE, REPEAT, INSTR, LOCATE, REGEXP_EXTRACT, REGEXP_REPLACE, REGEXP_LIKE

Date: DATE, YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, DATE_FORMAT, DATE_TRUNC, DATE_ADD, DATE_DIFF, CURRENT_DATE, CURRENT_TIMESTAMP, NOW, EXTRACT, TO_DATE, TO_TIMESTAMP, FROM_UNIXTIME

Conversion: CAST, COALESCE, NULLIF, NVL, IFNULL, GREATEST, LEAST

Conditional: IF, IIF, CASE WHEN ... THEN ... ELSE ... END

Column transformations (column_transformations)

Apply sequential transformations to existing columns. Transformations are processed in the order they appear.

"column_transformations": {
  "name": [
    {"type": "text", "operation": "uppercase"}
  ],
  "created_at": [
    {"type": "date", "operation": "year_month"}
  ],
  "amount": [
    {"type": "number", "operation": "round", "params": {"decimals": 2}}
  ]
}

Text transformations: uppercase, lowercase, trim, ltrim, rtrim, extract_domain, extract_before, extract_after, replace (params: find, replace), regexp_extract (params: pattern), regexp_replace (params: pattern, replacement)

Date transformations: date, year_month, year_week, year_quarter, year, hour, minute, extract_year, extract_month, extract_day, extract_hour, date_add_days (params: days), date_add_hours (params: hours), date_add_minutes (params: minutes)

Number transformations: round (params: decimals), floor, ceil, abs, truncate (params: decimals), divide (params: divisor), multiply (params: multiplier)

Type conversions: cast_to_text, cast_to_int, cast_to_number, cast_to_date, cast_to_timestamp

JOINs

Combine data from multiple tables:

{
  "table_name": "orders",
  "columns": ["orders.id", "customers.name", "orders.total"],
  "column_aggregations": ["none", "none", "none"],
  "joins": [
    {
      "tableName": "customers",
      "joinType": "LEFT",
      "conditions": [
        {
          "leftColumn": "orders.customer_id",
          "rightColumn": "customers.id"
        }
      ]
    }
  ]
}

JOIN types: INNER (only matching records), LEFT (all from main table + matches), RIGHT (all from joined table + matches), FULL (all from both), CROSS (cartesian product).

When using JOINs, prefix column names with the table name (e.g., orders.id, customers.name).

UNION ALL

Combine results from queries on different tables. All queries go inside the union array (minimum 2). The order_by and limit fields are placed at the root level.

{
  "union": [
    {
      "table_name": "sales_2025",
      "dest_collection_id": 12345,
      "columns": ["month", "revenue"],
      "column_aggregations": ["none", "sum"],
      "dimensions": ["month"]
    },
    {
      "table_name": "sales_2024",
      "columns": ["month", "revenue"],
      "column_aggregations": ["none", "sum"],
      "dimensions": ["month"]
    }
  ],
  "order_by": [{"column": "revenue", "direction": "desc"}],
  "limit": 500
}

Limits and restrictions

RestrictionValue
Maximum records per query1,000
Filter conditionsAND only
SubqueriesNot supported
DISTINCTNot supported (use count_distinct)
Simple UNIONNot supported (UNION ALL only)

Complete examples

Sales by region in the last month

{
  "dest_collection_id": 12345,
  "table_name": "sales",
  "columns": ["region", "revenue", "orders"],
  "column_aggregations": ["none", "sum", "count"],
  "dimensions": ["region"],
  "where_conditions": [
    {"column": "sale_date", "operator": "LAST_MONTH"}
  ],
  "order_by": [{"column": "revenue", "direction": "desc"}]
}

Top 10 customers by purchase value

{
  "dest_collection_id": 12345,
  "table_name": "orders",
  "columns": ["orders.customer_id", "customers.name", "orders.amount"],
  "column_aggregations": ["none", "none", "sum"],
  "dimensions": ["orders.customer_id", "customers.name"],
  "joins": [
    {
      "tableName": "customers",
      "joinType": "LEFT",
      "conditions": [
        {"leftColumn": "orders.customer_id", "rightColumn": "customers.id"}
      ]
    }
  ],
  "order_by": [{"column": "amount", "direction": "desc"}],
  "limit": 10
}

Filter with multiple conditions

{
  "dest_collection_id": 12345,
  "table_name": "leads",
  "columns": ["name", "email", "source", "score"],
  "where_conditions": [
    {"column": "score", "operator": ">=", "value": 80},
    {"column": "source", "operator": "IN", "value": ["google", "facebook"]},
    {"column": "email", "operator": "IS NOT NULL"},
    {"column": "created_at", "operator": "LAST_N_DAYS", "value": 90}
  ],
  "order_by": [{"column": "score", "direction": "desc"}],
  "limit": 100
}

– KSQL queries are in beta mode