Comparison to SQL

RhyDB queries have a pipeline syntax rather than SQL clauses.

Correspondence

SQL conceptRhyDB query-language operation
FROMStart the pipeline with a table name.
WHERE.filter(predicate)

SELECT columns

.project({fields})
computed column.map({name := expression})
GROUP BY.groupBy({aggregates}, {columns})
ORDER BY.orderBy({fields})

LIMIT / OFFSET

.limit(n) / .offset(n)

JOIN.join(otherPipeline, leftColumn = rightColumn)
UNION ALL.unionAll(otherPipeline)

The same summary in both styles

-- SQL
SELECT country, COUNT(*) AS count
FROM default
WHERE date >= DATE '2024-01-01'
GROUP BY country
ORDER BY count DESC
LIMIT 10;
-- RhyDB query language
default
  .filter(date >= '2024-01-01'::date)
  .groupBy({count := count()}, {country})
  .orderBy({count.desc()})
  .limit(10)

Differences

  • Order matters: each method receives the result produced immediately before it.
  • Records and sets use braces, and := assigns a name inside a record.
  • The available tables and columns are configured per RhyDB instance.
  • Sequence predicates and aggregations understand reference coordinates, mutations, and ambiguity.
  • RhyDB currently provides count() as its aggregate function; it is not a general SQL engine.
  • Missing values are tested with column.isNull() and column.isNotNull(); column = null is an error rather than the always-unknown comparison SQL allows.
  • ! is a set complement rather than SQL’s NOT. Comparisons never match null cells, so country <> 'Germany' drops the rows whose country is null while !(country = 'Germany') keeps them.
Reading a query

Read a RhyDB query from top to bottom as a series of intermediate tables. Operations such as map, project, and groupBy change the schema.