All Resources

R-77

Technology

Tessera DB Tutorial: Use the SQL Interface with JOINs and Aggregates

Tessera speaks real SQL. The same JOIN, GROUP BY, and ORDER BY you already know — over the same data as the graph, no new language required.

PAR2 Labs

August 29, 2026

4 min

Tessera DB Tutorial: Use the SQL Interface with JOINs and Aggregates

The SQL interface exists because most analysts already speak SQL and have no appetite to learn a new language just to evaluate Tessera. Same dialect they know, same results — over the same data the graph and vector dimensions see.

01

Step 1: Define tables

A CREATE TABLE statement declares a type with a flat property schema:

sql

CREATE TABLE accounts (
  id      INTEGER PRIMARY KEY,
  name    TEXT,
  balance DOUBLE PRECISION
);

CREATE TABLE transfers (
  id          INTEGER PRIMARY KEY,
  from_id     INTEGER,
  to_id       INTEGER,
  amount      DOUBLE PRECISION,
  created_at  TIMESTAMP
);

02

Step 1: Define tables — the same rows as a graph

Foreign keys become real graph edges when you provide endpoint mappings on ingest, so the same rows are queryable as tables here and as a graph elsewhere.

03

Step 2: INSERT

sql

INSERT INTO accounts (id, name, balance)
VALUES (1, 'Alice', 50000.0);

INSERT INTO accounts (id, name, balance) VALUES
  (2, 'Bob', 12000.0),
  (3, 'Carol', 85000.0);

04

Step 3: SELECT with WHERE, ORDER BY, LIMIT

sql

SELECT name, balance
FROM accounts
WHERE balance > 10000
ORDER BY balance DESC
LIMIT 10;

05

Step 4: JOIN

sql

SELECT t.id, t.amount, a.name AS sender, b.name AS receiver
FROM transfers t
INNER JOIN accounts a ON t.from_id = a.id
INNER JOIN accounts b ON t.to_id   = b.id
WHERE t.amount > 1000
ORDER BY t.amount DESC;

The goal is no surprises for SQL users.

06

Step 4: JOIN — how joins resolve

INNER JOIN and LEFT JOIN both work, resolved against the underlying graph rather than a flat row scan.

07

Step 5: GROUP BY and aggregates

sql

SELECT a.name, COUNT(*) AS tx_count, SUM(t.amount) AS total
FROM transfers t
INNER JOIN accounts a ON t.from_id = a.id
GROUP BY a.name
HAVING SUM(t.amount) > 5000
ORDER BY total DESC;

08

Step 5: GROUP BY and aggregates — what is supported

COUNT, SUM, AVG, MIN, and MAX all work, and HAVING filters on aggregate results.

09

Step 6: LIKE, IN, BETWEEN

sql

SELECT * FROM accounts WHERE name LIKE 'A%';
SELECT * FROM accounts WHERE id IN (1, 2, 3);
SELECT * FROM accounts WHERE balance BETWEEN 10000 AND 100000;

10

Real SQL, not a toy subset

Filters, joins, aggregation, upserts, prepared statements, materialised views, and triggers are all part of the relational dimension — and your existing BI tools and ORMs can talk to it over the PostgreSQL wire protocol. The goal is no surprises for SQL users.

Key Takeaways

01

Declared tables with CREATE TABLE and inserted rows, one at a time and several at once.

02

Filtered, sorted and limited results with WHERE, ORDER BY and LIMIT.

03

Joined transfers to accounts with INNER JOIN, and aggregated with GROUP BY, HAVING, COUNT and SUM.

04

Matched rows with LIKE, IN and BETWEEN, over the same data the graph and vector dimensions see.


PAR2 Labs · Technology

Work With Us

Have a problem worth solving?