Quartiles with NTILE in SQL
NTILE splits rows into equal-sized buckets such as quartiles or deciles, so you can label customers or products by where they fall in the distribution.
Example query
This example assumes: customer_value(customer_id bigint, lifetime_value numeric). It is written in PostgreSQL syntax, and your table and column names will differ from these.
SELECT customer_id,
lifetime_value,
NTILE(4) OVER (ORDER BY lifetime_value DESC) AS quartile
FROM customer_value
ORDER BY lifetime_value DESC;Quartile cut-off values instead of labels
SELECT PERCENTILE_CONT(ARRAY[0.25, 0.5, 0.75]) WITHIN GROUP (ORDER BY lifetime_value) AS quartile_cutoffs
FROM customer_value;How it works
- NTILE(4) divides the ordered rows into four groups of nearly equal size, numbered 1 to 4.
- Ordering descending makes quartile 1 the highest-value customers.
- The alternative returns the three cut-off values that separate the quartiles, which is useful when you want thresholds rather than labels.
MySQL, BigQuery, SQL Server and SQLite differences
- NTILE is available in PostgreSQL, MySQL 8+, SQL Server, BigQuery and SQLite 3.25+. The percentile-array form is PostgreSQL-specific.
Common mistakes
- NTILE puts equal values in different buckets when they straddle a boundary, so identical customers can get different quartiles.
- When the row count does not divide evenly, the first buckets get one extra row.
- Bucket by quantile and by fixed value ranges are different analyses; histograms use value ranges.
Ask for it in plain English
Instead of writing the query yourself, you can type the question. SchemaChat turns it into SQL against your connected database or uploaded file, runs it, and shows the SQL and the figures it used so you can check the answer before you share it. Check that the query matches the definition your business uses.
- Split customers into quartiles by lifetime value.
- Which customers are in the top 10% by spend?