← all features

SQL · live examples

SQL over a hash-keyed substrate.

OriginChain runs standard SQL directly on the same store that serves vectors, full-text, and graph hops. No sync jobs, no second engine — the rows your joins touch are the rows every other shape sees.

01
Declare
Tables and indexes come from the schema manifest — no query-time DDL surprises.
02
Plan
Cost-based planning with cardinality bounds keeps join order honest.
03
Execute
A volcano executor streams over prefix scans — measured, not cached.
checking instance…one substrate · sql / graph / vector / fts / nql
Foundations
01

Projection + WHERE

easy

Customers in Pune — projection, predicate, limit.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT customer_id, name, city, segment FROM customers WHERE city = 'Pune' LIMIT 5"
}
02

INNER JOIN

easy

Customers joined to the accounts they own.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT c.name, a.account_id, a.type, a.balance_inr FROM customers c JOIN accounts a ON a.customer_id = c.customer_id WHERE c.segment = 'premium' LIMIT 5"
}
03

GROUP BY aggregate

easy

Transaction volume per account type — SUM, COUNT, GROUP BY.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT a.type, COUNT(t.txn_id) AS txns, SUM(t.amount_inr) AS volume_inr FROM transactions t JOIN accounts a ON a.account_id = t.from_account GROUP BY a.type"
}
04

Portfolio snapshot — COUNT DISTINCT

easy

The one-line exec question: how many customers, accounts, and cities are we looking at?

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT COUNT(DISTINCT c.customer_id) AS customers, COUNT(a.account_id) AS accounts, COUNT(DISTINCT c.city) AS cities FROM customers c JOIN accounts a ON a.customer_id = c.customer_id"
}
Intermediate patterns
05

LEFT JOIN with empty side

intermediate

Accounts that have never transacted — the NULL side of a LEFT JOIN.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT a.account_id, a.type, t.txn_id FROM accounts a LEFT JOIN transactions t ON t.from_account = a.account_id WHERE t.txn_id IS NULL LIMIT 5"
}
06

Self-join

intermediate

Pairs of customers sharing an employer — the classic self-join.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT c1.name AS a, c2.name AS b, c1.employer FROM customers c1 JOIN customers c2 ON c1.employer = c2.employer AND c1.customer_id < c2.customer_id LIMIT 5"
}
07

Three-way join + date range

intermediate

Customers → accounts → transactions in one query: who moved the most money in Q2, by segment.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT c.segment, c.name, COUNT(t.txn_id) AS txns, SUM(t.amount_inr) AS moved_inr FROM customers c JOIN accounts a ON a.customer_id = c.customer_id JOIN transactions t ON t.from_account = a.account_id WHERE t.ts BETWEEN '2026-04-01' AND '2026-06-30' GROUP BY c.segment, c.name ORDER BY moved_inr DESC LIMIT 5"
}
08

IN subquery — flagged-account exposure

intermediate

Uncorrelated subquery: every customer whose account sent money to an account that appears in the fraud-flag list.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT DISTINCT c.customer_id, c.name FROM customers c JOIN accounts a ON a.customer_id = c.customer_id JOIN transactions t ON t.from_account = a.account_id WHERE t.to_account IN (SELECT account_id FROM flags WHERE reason = 'mule_suspect')"
}
09

Conditional aggregate + HAVING

intermediate

Risk mix per segment — SUM(CASE …) pivots inside the aggregate, HAVING filters the groups.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT c.segment, COUNT(*) AS customers, SUM(CASE WHEN a.balance_inr < 0 THEN 1 ELSE 0 END) AS in_debt, AVG(a.balance_inr) AS avg_balance FROM customers c JOIN accounts a ON a.customer_id = c.customer_id GROUP BY c.segment HAVING COUNT(*) > 10"
}
10

Dormant high-value customers

intermediate

Churn-risk radar: balances over 5 lakh with no transaction in 90 days — join, subquery exclusion, threshold.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT c.customer_id, c.name, a.balance_inr FROM customers c JOIN accounts a ON a.customer_id = c.customer_id WHERE a.balance_inr > 500000 AND a.account_id NOT IN (SELECT from_account FROM transactions WHERE ts >= '2026-04-07') ORDER BY a.balance_inr DESC LIMIT 5"
}
11

Monthly trend — GROUP BY month

intermediate

Transaction volume by calendar month — the chart every ops review opens with, straight from GROUP BY.

request
POST /v1/tenants/:t/sql
{
  "sql": "SELECT SUBSTR(t.ts, 1, 7) AS month, COUNT(*) AS txns, SUM(t.amount_inr) AS volume_inr FROM transactions t GROUP BY SUBSTR(t.ts, 1, 7) ORDER BY month"
}