Hugging Face, End to EndLesson 42 of 75

Contents

Hugging Face, End to End

Lesson 42 of 75. Sign in to keep your place.

Module 5 · Datasets, and the work that happens before any model

Query a dataset with SQL before downloading it

8 min read

What a GROUP BY over HTTP actually fetchesRead the footerColumn statisticsPick row groupsSkip all the restRange requestsOne column onlyAggregate locallyA few megabytesA count over a fifty-gigabyte corpus can transfer a few megabytes, because parquet keeps its columnstatistics in the file footer and a query on one column never touches the others. This is why classbalance is a question you can answer on a phone before downloading anything.
A count over a fifty-gigabyte corpus can transfer a few megabytes, because parquet keeps its column statistics in the file footer and a query on one column never touches the others. This is why class balance is a question you can answer on a phone before downloading anything.

Figure

The conversion nobody mentions

When a dataset is published publicly on the Hub, the platform converts it to Parquet automatically and serves those files. The dataset viewer on the page is reading them. So is anything else that can read parquet over HTTP.

That gives you a capability most people never use: running real SQL against a dataset you have not downloaded, on a laptop, in seconds.

DuckDB, which is free and is one pip install

Bash
pip install duckdb
Python
import duckdb

q = """
SELECT label, COUNT(*) AS n
FROM 'hf://datasets/imdb/plain_text/train-*.parquet'
GROUP BY label
"""
print(duckdb.sql(q).df())

DuckDB reads parquet metadata first, works out which row groups it needs, and fetches only those byte ranges. A count over a 50 GB dataset can transfer a few megabytes, because column statistics live in the footer and a GROUP BY on one column never touches the others.

The file paths are discoverable from the API:

Python
import requests
r = requests.get("https://datasets-server.huggingface.co/parquet?dataset=imdb").json()
for f in r["parquet_files"][:3]:
    print(f["split"], f["url"], f["size"])

The five questions worth asking before you download

  1. How big is each class? A dataset described as balanced frequently is not.
SQL
SELECT label, COUNT(*) FROM 'hf://datasets/.../train-*.parquet' GROUP BY label
  1. How long are the texts? This decides your max_length and therefore your compute bill.
SQL
SELECT MIN(len), MAX(len), MEDIAN(len),
       QUANTILE_CONT(len, 0.95) AS p95
FROM (SELECT LENGTH(text) AS len FROM '...')
  1. Are there duplicates?
SQL
SELECT COUNT(*) - COUNT(DISTINCT text) AS dupes FROM '...'
  1. Does the test split overlap the train split? The leakage check, and the one that invalidates published results:
SQL
SELECT COUNT(*) FROM 'hf://datasets/.../test-*.parquet' t
JOIN 'hf://datasets/.../train-*.parquet' r ON t.text = r.text
  1. What does the rare class actually look like? Pull twenty rows and read them. Ten minutes of reading beats an hour of aggregate statistics, every time.

The viewer itself does more than you think

On the dataset page: full-text search across rows, sorting by column, filtering, and a per-column statistics panel showing distributions, null counts and distinct values. For a first look this is faster than writing anything, and it costs no download.

It also honestly shows what many cards do not: that a “multilingual” corpus is 94% English, or that a column described as clean text is 3% null.

Turning a query into a view of the whole corpus

One more pattern is worth having. Aggregates answer what is in a dataset; a sample answers what it is like. Combine them:

SQL
SELECT label, text
FROM 'hf://datasets/.../train-*.parquet'
USING SAMPLE 20 ROWS

DuckDB’s USING SAMPLE pulls a random subset without reading everything, so you can read twenty real rows of a terabyte corpus on a phone tethering connection. Reading twenty rows tells you about formatting, boilerplate, truncation and encoding problems that no aggregate will ever surface.

The limits

  • Public datasets only by default. Gated and private ones need a token, and very large ones may be only partially converted, which the viewer states.
  • Some datasets have no viewer at all: a custom loading script, an unsupported format, or an explicit opt-out. Absence is not a red flag by itself, but it does mean you are back to reading files by hand.
  • The parquet copy can lag a very recent update by a short period.

Querying your own files the same way

DuckDB is not a Hub feature; it is a local database that happens to read remote parquet. Everything above works on a folder of your own files:

Python
duckdb.sql("SELECT COUNT(*) FROM 'data/*.parquet' WHERE lang = 'hi'")

And it goes the other way, straight into the library:

Python
from datasets import Dataset
df = duckdb.sql("SELECT text, label FROM '...' WHERE LENGTH(text) BETWEEN 50 AND 2000").df()
ds = Dataset.from_pandas(df)

SQL for selection and aggregation, datasets for the training path. That combination handles almost everything without Spark, without a cluster, and on hardware you already own.

Do this now

Pick any public dataset you have considered using and run the five queries above against it without downloading it. Most people find at least one thing the card did not say: usually the class balance or the length distribution, and occasionally the train–test overlap.

Every lesson here is open. Your progress is recorded once you pass the Image Generation, in Practice exam.

Check your understanding

Why can a GROUP BY over a 50 GB Hub dataset transfer only a few megabytes?

Pick the one you would defend. Your answer stays private.

Next lesson · 9 minTurning your files into a dataset

Stuck on something?Ask Arjun, your AI tutor

How to cite: Addaly (2026) ‘Query a dataset with SQL before downloading it’, in Hugging Face, End to End. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/hugging-face/the-viewer-and-sql (Accessed: 13 October 2026).