The portable way to grab a random handful of rows — works everywhere, but sorts every row in the table to do it:
-- PostgreSQL, DuckDB
SELECT * FROM products ORDER BY random() LIMIT 20;
-- MySQL, BigQuery
SELECT * FROM products ORDER BY RAND() LIMIT 20;
-- SQLite
SELECT * FROM products ORDER BY RANDOM() LIMIT 20;
For a large table, most warehouses and PostgreSQL offer real sampling clauses that skip most of the data instead of sorting all of it:
-- Snowflake (SAMPLE / TABLESAMPLE are interchangeable keywords)
SELECT * FROM products SAMPLE (20 ROWS);
SELECT * FROM products SAMPLE (1); -- ~1% of rows, BERNOULLI-style by default
-- BigQuery
SELECT * FROM products TABLESAMPLE SYSTEM (10 PERCENT);
-- DuckDB
SELECT * FROM products USING SAMPLE 20;
SELECT * FROM products USING SAMPLE 1%;
-- PostgreSQL
SELECT * FROM products TABLESAMPLE BERNOULLI (1); -- ~1% of rows, scans every row (slower, more random)
SELECT * FROM products TABLESAMPLE SYSTEM (1); -- ~1% of rows, whole-page sampling (faster, clumpier)
ORDER BY RANDOM()/RAND() LIMIT nsorts the whole table — it assigns every row a random sort key and fully sorts them just to keep a handful. Fine for a small table; a full scan-and-sort for a large one. Snowflake, BigQuery, DuckDB and PostgreSQL all have a dedicated sampling clause that reads a random subset of storage blocks instead of touching every row — much faster, at the cost of an approximate (not exact) row count. MySQL and SQLite have no table-sampling clause at all, soORDER BY RAND()/RANDOM() LIMIT n(or sampling on an indexed random column you maintain yourself) is the only built-in option there.