Skip to content
Reference / SQL Random Samples with USING SAMPLE
Reference

SQL Random Samples with USING SAMPLE

USING SAMPLE returns a random subset of a table: an exact number of rows, or a percentage. A seed makes the same sample come back every time.

USING SAMPLE after a table returns a random subset of its rows. Ask for a count (5 rows) or a share (10 percent), and add a seed when you need the same sample again. It's how you look at a few typical rows of a big table, or estimate an average without reading everything.

Five random rows, the same five every time
select ad_group_id, activity_date, clicks
from daily_performance
using sample 5 rows (reservoir, 42)
order by all

These examples use the browser sample of Marketing Campaigns' daily_performance, which has 4,827 rows. Change the 42 and you get a different five.

Three sampling methods

Method Returns Default for
reservoir Exactly the number of rows you ask for n rows
bernoulli Each row kept independently with that probability, so close to the percentage but not exact
system Whole chunks of 2,048 rows, kept or dropped together. Fast on a huge table, useless on a small one n percent

So name bernoulli whenever you ask for a percentage. With a seed, this returns 486 rows, close to 10% of 4,827:

About 10%, the same rows every run
select count(*) as sampled,
       round(avg(clicks), 2) as avg_clicks
from daily_performance
using sample 10 percent (bernoulli, 42)

Its average of 13.92 clicks is near the full table's 13.76. That gap is what a sample costs you.

Seeds and the TABLESAMPLE spelling

The second value in the parentheses is the seed: (bernoulli, 42). DuckDB also accepts the SQL standard's TABLESAMPLE with REPEATABLE. These two return the same 486 rows:

Two spellings, one sample
select count(*) from daily_performance
using sample 10 percent (bernoulli, 42);

select count(*) from daily_performance
tablesample bernoulli(10%) repeatable (42);

Without a seed, every run draws a new sample. A seed repeats a sample of the same data; once the table changes, expect a different sample.

The portable form

Sorting by a random number and keeping the first rows works almost everywhere: order by random() limit 5 in DuckDB, PostgreSQL, and SQLite, ORDER BY RAND() in MySQL, and ORDER BY NEWID() in SQL Server. It sorts the whole table to do it, which a real sample avoids.

What can go wrong

  • A percentage on a small table returns all or nothing. With no method named, using sample 10% uses system sampling. On these 4,827 rows, 30 runs returned 0 rows most of the time, and otherwise 731, 2,048, or 2,779: whole chunks, never anything near 483.
  • The sample is taken before WHERE. 336 rows have more than 50 clicks, but sampling five rows of the table first and then filtering keeps none of them. Filter in a subquery and sample that.
  • PostgreSQL's syntax fails. tablesample bernoulli (10) is a percentage in PostgreSQL and a row count in DuckDB, which Bernoulli can't take: Sample method Bernoulli cannot be used with a discrete sample count. Write bernoulli (10%).
Sample, then filter
select count(*) as kept
from daily_performance
where clicks > 50
using sample 5 rows (reservoir, 42)
Filter, then sample
select count(*) as kept
from (
  select *
  from daily_performance
  where clicks > 50
) as busy_days
using sample 5 rows (reservoir, 42)

The first returns 0 and the second returns 5.

PostgreSQL's spelling
select count(*)
from daily_performance
tablesample bernoulli (10) repeatable (42)

How other databases differ

Engine Syntax Notes
DuckDB USING SAMPLE, TABLESAMPLE Rows or a percentage; a bare number means rows
PostgreSQL TABLESAMPLE BERNOULLI (10) REPEATABLE (42) Percentage only; SYSTEM samples whole pages
SQL Server TABLESAMPLE (10 PERCENT) Samples whole pages, so small tables come back all or nothing
Snowflake SAMPLE (10), SAMPLE (5 ROWS) SEED (42) to repeat
MySQL, SQLite None ORDER BY RAND() / random() and LIMIT
Dialect note

PostgreSQL's SYSTEM and SQL Server's TABLESAMPLE skip whole pages, as DuckDB's system skips chunks. That's quick, and on a small table the count can land far from the percentage. Name the row-by-row method, BERNOULLI, when the result has to be close.