Skip to content
Monu Tools

Query a CSV with SQL, No Database Setup Required

By Maxwell AboagyeLast updated August 5, 2026

You have a CSV and a question: which region sells the most, what are the biggest orders, which products move enough units to matter. Excel can answer these, but pivot tables are fiddly and Excel quietly rewrites your data on the way in. SQL answers them in one readable line each, and you do not need to install a database to use it. The Query CSV with SQL tool loads your CSV into an in-memory SQLite table right in the browser, so you can go from file to answer in under a minute. This guide walks one small dataset through the five queries that cover most everyday analysis.

Try the Query CSV (SQL) toolRun SQL SELECT queries against a CSV in your browser: it loads into a table you can filter, group and join. Nothing is uploaded.

The dataset

Everything below runs against this eight-row orders file. Paste it into the tool and follow along.

order_id,region,product,quantity,unit_price
0012,West,Notebook,4,3.50
0013,East,Pen,10,1.25
0014,West,Pen,6,1.25
0015,North,Notebook,2,3.50
0016,East,Notebook,5,3.50
0017,West,Backpack,1,24.00
0018,North,Pen,12,1.25
0019,East,Backpack,2,24.00

How a CSV becomes a table

When you hit Run, the tool parses the CSV and creates a table (named data by default, you can rename it) inside a throwaway SQLite database. The header row becomes the column names, and each following line becomes one row. Cells that look like plain numbers are stored as numbers so that arithmetic and sorting behave numerically; everything else stays text. One deliberate exception: a value with a leading zero, like the order IDs above, does not look like a plain number and is kept as text, so your IDs survive intact.

ColumnSample valueStored as
order_id0012text (leading zero preserved)
regionWesttext
productNotebooktext
quantity4number
unit_price3.50number

Filter rows with WHERE

Start with the simplest question: show me the orders from one region.

SELECT order_id, product, quantity
FROM data
WHERE region = 'West';
order_id  product   quantity
0012      Notebook  4
0014      Pen       6
0017      Backpack  1

Text values are compared in single quotes, and by default string comparison in SQLite is case sensitive, so 'west' would match nothing here. You can combine conditions with AND and OR, for example WHERE region = 'West' AND quantity > 3, which returns just orders 0012 and 0014.

Compute a column, then find the top N

The file stores quantity and unit price, but the number you actually care about is revenue. A SELECT can compute it on the fly, and the AS keyword names the result column. Add ORDER BY and LIMIT and you have a top-3 list.

SELECT order_id, region, product,
       quantity * unit_price AS revenue
FROM data
ORDER BY revenue DESC
LIMIT 3;
order_id  region  product   revenue
0019      East    Backpack  48
0017      West    Backpack  24
0016      East    Notebook  17.5

Check the arithmetic: order 0019 is 2 backpacks at 24.00 each, so 48; order 0017 is 1 at 24.00; order 0016 is 5 notebooks at 3.50, so 17.5. DESC sorts largest first (the default is ascending), and LIMIT 3 keeps only the top of the sorted list. Because quantity and unit_price were stored as numbers, the multiplication just works; if they had been text you would get concatenation-era surprises instead.

Summarize with GROUP BY

GROUP BY collapses rows that share a value into one summary row each, and aggregate functions describe each group: COUNT(*) counts the rows, SUM adds a column up, AVG averages it. This is the pivot table, minus the pivot table.

SELECT region,
       COUNT(*) AS orders,
       SUM(quantity * unit_price) AS revenue,
       ROUND(AVG(quantity * unit_price), 2) AS avg_order
FROM data
GROUP BY region
ORDER BY revenue DESC;
region  orders  revenue  avg_order
East    3       78       26
West    3       45.5     15.17
North   2       22       11

Verify one group by hand. East has orders 0013 (10 x 1.25 = 12.5), 0016 (5 x 3.50 = 17.5), and 0019 (2 x 24.00 = 48), which sum to 78 across 3 orders, an average of 26. West is 14 + 7.5 + 24 = 45.5, and 45.5 / 3 rounds to 15.17. North is 7 + 15 = 22 over 2 orders. AVG always returns a floating point value in SQLite, so ROUND(x, 2) keeps the output tidy.

Filter groups with HAVING

WHERE filters rows before grouping; HAVING filters the groups afterwards, so it is the place for conditions on aggregates. Which products moved at least 10 units in total?

SELECT product, SUM(quantity) AS units
FROM data
GROUP BY product
HAVING SUM(quantity) >= 10
ORDER BY units DESC;
product   units
Pen       28
Notebook  11

Pens total 10 + 6 + 12 = 28 units and notebooks 4 + 2 + 5 = 11, so both pass. Backpacks total only 1 + 2 = 3, so HAVING drops that group. Writing WHERE SUM(quantity) >= 10 instead is an error, because WHERE runs per row, before any groups exist.

Where to go from here

These five clauses (WHERE, ORDER BY, LIMIT, GROUP BY, HAVING) cover a surprising share of real-world CSV questions, and they compose: filter first, group what remains, keep the interesting groups, sort, take the top N. When a query misbehaves, the cause is often the file rather than the SQL: a stray comma inside an unquoted field shifts every column after it, so it pays to understand how CSV quoting works. And if a numeric-looking column must stay text, quote it in the source or rename the ID column values, because the type guess happens at load time.

When one table stops being enough, the same engine scales up. The SQLite Online tool gives you a full scratch database in the browser where you can create several tables and join them, and the CSV to SQL converter turns a CSV into CREATE TABLE and INSERT statements you can run anywhere, including a production database.

Run SQL on your CSVRun SQL SELECT queries against a CSV in your browser: it loads into a table you can filter, group and join. Nothing is uploaded.

Sources

Related articles