SQL basics
If you have used SUMIF, FILTER or a pivot table, you already understand what
SQL does — it just says it differently. This page covers the parts you need for
SQL Cell. It is not a full SQL course.
Every example assumes a file called sales.csv attached in the Files panel,
with columns date, region, product, units and total.
The shape of a query
Section titled “The shape of a query”SELECT region, totalFROM 'sales.csv'WHERE units > 10ORDER BY total DESCLIMIT 20;Read it as: take these columns, from this file, keeping only rows that match, sorted this way, stopping after 20 rows.
The clauses always appear in that order. All of them except SELECT and FROM
are optional.
Picking columns — SELECT
Section titled “Picking columns — SELECT”SELECT * FROM 'sales.csv'; -- every columnSELECT region, total FROM 'sales.csv'; -- just these twoSELECT total * 0.2 AS vat FROM 'sales.csv';AS names the result column, which is what ends up as the header in your sheet.
Name your calculated columns — it makes the inserted block readable.
Filtering rows — WHERE
Section titled “Filtering rows — WHERE”SELECT * FROM 'sales.csv'WHERE region = 'EMEA' AND units >= 10 AND date >= '2026-01-01';Text goes in single quotes; numbers do not. Useful comparisons:
= <> |
equal, not equal |
> < >= <= |
ordering |
IN ('EMEA', 'APAC') |
any of these |
BETWEEN 10 AND 50 |
inclusive range |
LIKE '%widget%' |
contains (% is the wildcard) |
IS NULL / IS NOT NULL |
empty or not |
Summarising — GROUP BY
Section titled “Summarising — GROUP BY”This is the pivot table. GROUP BY says which column to collapse on, and the
aggregate functions say what to do with the rows in each group.
SELECT region, count(*) AS orders, sum(total) AS revenue, avg(total) AS average_order, max(total) AS biggestFROM 'sales.csv'GROUP BY regionORDER BY revenue DESC;The rule that catches everyone: every column in SELECT must either be in
GROUP BY or be wrapped in an aggregate function. product in the query above
would be an error — the database has no way to pick which product to show for a
whole region.
To filter on an aggregate, use HAVING rather than WHERE:
SELECT region, sum(total) AS revenueFROM 'sales.csv'GROUP BY regionHAVING sum(total) > 10000;WHERE filters rows before grouping; HAVING filters groups after.
Combining two files — JOIN
Section titled “Combining two files — JOIN”JOIN is VLOOKUP, without the fragility.
SELECT c.name, sum(o.total) AS lifetime_valueFROM 'orders.csv' oJOIN 'customers.csv' c ON o.customer_id = c.idGROUP BY c.nameORDER BY lifetime_value DESC;o and c are aliases — short names for the files so you can write o.total
instead of repeating the filename. ON says which columns must match.
A plain JOIN keeps only rows that matched in both files. LEFT JOIN keeps
every row from the first file whether or not it matched, filling the rest with
nulls — use it when a missing match is itself the thing you are looking for.
Handy functions
Section titled “Handy functions”SELECT round(avg(total), 2) AS avg_total, upper(region) AS region, coalesce(discount, 0) AS discount, -- null becomes 0 date_trunc('month', date) AS month, -- group by month strftime(date, '%Y-%m') AS labelFROM 'sales.csv'GROUP BY region, month, label;Things that will trip you up
Section titled “Things that will trip you up”- Column names are case-sensitive. If your header is
Total, thentotalwill not find it. Wrap awkward names in double quotes:"order id". - Single quotes are for values, double quotes are for names.
'EMEA'is text;"order id"is a column. - A trailing comma before
FROMis an error. Easy to leave behind when you delete a column. - Numbers that arrived as text will not add up. Check the Columns tab in
the preview — if a numeric column says
VARCHAR, cast it:CAST(total AS DOUBLE).
Where to go next
Section titled “Where to go next”SQL Cell runs DuckDB, so anything in the
DuckDB SQL documentation works here —
including window functions, PIVOT, and reading several files at once with a
glob such as 'data/*.csv'.