Query a CSV with SQL, No Database Setup Required
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.00How 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.
| Column | Sample value | Stored as |
|---|---|---|
| order_id | 0012 | text (leading zero preserved) |
| region | West | text |
| product | Notebook | text |
| quantity | 4 | number |
| unit_price | 3.50 | number |
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 1Text 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.5Check 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 11Verify 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 11Pens 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
CSV Quoting Rules: Why Splitting on Commas Breaks Your Data
What RFC 4180 actually requires: when a CSV field must be quoted, how to escape a double quote, and why naive split-on-comma parsers corrupt rows.
Stop Excel Silently Changing Your CSV Data (Zeros, Dates, Big Numbers)
Excel quietly rewrites CSV data on open: dropped leading zeros, gene names turned into dates, IDs in scientific notation. Why it happens and how to stop it.