TUTORIAL

Learn Teide in 10 Minutes

A hands-on walkthrough that takes you from zero to writing real queries. You'll create tables, filter data, aggregate results, join tables, and use window functions.

Prerequisites: Make sure you've built Teide first. See Getting Started for installation instructions.

Step 1: Launch the REPL

Start the interactive shell:

cargo run --release --features cli

You'll see the teide> prompt. Every SQL statement must end with a semicolon. Let's dive in.

Step 2: Create Your First Table

Let's build a small employees dataset directly in the REPL:

CREATE TABLE employees (id INTEGER, name VARCHAR, dept VARCHAR, salary REAL);

INSERT INTO employees VALUES
  (1, 'Alice',  'engineering', 95000.0),
  (2, 'Bob',    'engineering', 87000.0),
  (3, 'Carol',  'marketing',   72000.0),
  (4, 'Dave',   'marketing',   68000.0),
  (5, 'Eve',    'engineering', 92000.0),
  (6, 'Frank',  'sales',       78000.0),
  (7, 'Grace',  'sales',       81000.0),
  (8, 'Heidi',  'marketing',   74000.0);

Check it worked:

SELECT COUNT(*) FROM employees;
8

Step 3: Query the Data

Select all rows:

SELECT * FROM employees ORDER BY id;

Pick specific columns:

SELECT name, salary FROM employees ORDER BY salary DESC;
Alice 95000.0 Eve 92000.0 Bob 87000.0 Grace 81000.0 Frank 78000.0 Heidi 74000.0 Carol 72000.0 Dave 68000.0

Use aliases to rename columns in the output:

SELECT name, salary / 12.0 AS monthly FROM employees ORDER BY monthly DESC LIMIT 3;
Alice 7916.666667 Eve 7666.666667 Bob 7250.0

Step 4: Filter with WHERE

Find engineers earning over 90k:

SELECT name, salary FROM employees
WHERE dept = 'engineering' AND salary > 90000.0
ORDER BY salary DESC;
Alice 95000.0 Eve 92000.0

Use BETWEEN, IN, and LIKE:

-- Salary range
SELECT name, salary FROM employees WHERE salary BETWEEN 75000.0 AND 90000.0 ORDER BY salary;

-- Multiple departments
SELECT name, dept FROM employees WHERE dept IN ('engineering', 'sales') ORDER BY name;

-- Pattern matching
SELECT name FROM employees WHERE name LIKE '%a%' ORDER BY name;

Step 5: Aggregate with GROUP BY

Get summary statistics per department:

SELECT
  dept,
  COUNT(*)   AS headcount,
  AVG(salary) AS avg_salary,
  MIN(salary) AS min_salary,
  MAX(salary) AS max_salary
FROM employees
GROUP BY dept
ORDER BY avg_salary DESC;
engineering 3 91333.333333 87000.0 95000.0 sales 2 79500.0 78000.0 81000.0 marketing 3 71333.333333 68000.0 74000.0

Use HAVING to filter groups:

SELECT dept, AVG(salary) AS avg_sal
FROM employees
GROUP BY dept
HAVING AVG(salary) > 75000.0
ORDER BY avg_sal DESC;
engineering 91333.333333 sales 79500.0

Step 6: Join Tables

Create a departments table and join it with employees:

CREATE TABLE departments (name VARCHAR, floor INTEGER, budget REAL);

INSERT INTO departments VALUES
  ('engineering', 3, 500000.0),
  ('marketing',   2, 200000.0),
  ('sales',       1, 300000.0),
  ('hr',          2, 150000.0);

INNER JOIN — only rows that match in both tables:

SELECT e.name, e.dept, d.floor, d.budget
FROM employees e
INNER JOIN departments d ON e.dept = d.name
ORDER BY e.name;
Alice engineering 3 500000.0 Bob engineering 3 500000.0 Carol marketing 2 200000.0 Dave marketing 2 200000.0 Eve engineering 3 500000.0 Frank sales 1 300000.0 Grace sales 1 300000.0 Heidi marketing 2 200000.0

LEFT JOIN — keep all departments, even those with no employees:

SELECT d.name AS dept, COUNT(e.id) AS headcount
FROM departments d
LEFT JOIN employees e ON d.name = e.dept
GROUP BY d.name
ORDER BY headcount DESC;
engineering 3 marketing 3 sales 2 hr 0

Step 7: Window Functions

Rank employees by salary within each department:

SELECT
  name, dept, salary,
  ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rank
FROM employees
ORDER BY dept, rank;
Alice engineering 95000.0 1 Eve engineering 92000.0 2 Bob engineering 87000.0 3 Heidi marketing 74000.0 1 Carol marketing 72000.0 2 Dave marketing 68000.0 3 Grace sales 81000.0 1 Frank sales 78000.0 2

Compute a running total of salary per department:

SELECT
  name, dept, salary,
  SUM(salary) OVER (PARTITION BY dept ORDER BY salary) AS running_total
FROM employees
ORDER BY dept, salary;
Bob engineering 87000.0 87000.0 Eve engineering 92000.0 179000.0 Alice engineering 95000.0 274000.0 Dave marketing 68000.0 68000.0 Carol marketing 72000.0 140000.0 Heidi marketing 74000.0 214000.0 Frank sales 78000.0 78000.0 Grace sales 81000.0 159000.0

Compare each salary to the department average:

SELECT
  name, dept, salary,
  AVG(salary) OVER (PARTITION BY dept) AS dept_avg
FROM employees
ORDER BY dept, name;

Step 8: Subqueries & CTEs

Find employees in departments with above-average budgets:

SELECT e.name, e.dept, d.budget
FROM employees e
INNER JOIN departments d ON e.dept = d.name
WHERE d.budget > (SELECT AVG(budget) FROM departments)
ORDER BY e.name;

Use a CTE (WITH clause) for cleaner multi-step logic:

WITH dept_stats AS (
  SELECT dept, COUNT(*) AS headcount, AVG(salary) AS avg_salary
  FROM employees
  GROUP BY dept
)
SELECT dept, headcount, avg_salary
FROM dept_stats
WHERE headcount > 2
ORDER BY avg_salary DESC;

Step 9: Load a CSV File

Teide can load CSV files directly:

CREATE TABLE trades AS SELECT * FROM read_csv('trades.csv');

Or start the REPL with a CSV preloaded as table t:

teide trades.csv

Then query immediately:

SELECT * FROM t ORDER BY price DESC LIMIT 10;

Step 10: Useful REPL Commands

While in the REPL, these dot commands help you explore:

CommandWhat it does
.tablesList all tables with row and column counts
.mode csvSwitch output to CSV format
.mode jsonSwitch output to JSON format
.mode tableSwitch back to table format (default)
.timer onShow query execution time
.memShow memory usage statistics
.quitExit the REPL

Tip: Press Tab for auto-completion of table names, column names, and SQL keywords.

Next Steps

EXPLORE

SQL Reference

Complete reference for all supported SQL statements, functions, and operators.

TOOLS

CLI / REPL

All launch modes, dot commands, output formats, and keyboard shortcuts.

CONNECT

PgWire Server

Connect with psql, DBeaver, or any PostgreSQL client.

EMBED

Rust API

Use Teide as a library in your Rust application.