runtime
46 / 88

lesson 46 Window functions · advanced

NTILE & balanced ranking buckets

Split ordered rows into ranking buckets.

the idea

NTILE divides an ordered partition into a requested number of buckets. Bucket row counts differ by at most one, with larger buckets first. It may separate equal values; use a deterministic tie-breaker if that is acceptable.

tables in this lesson

The challenges use this data. Each column shows its type underneath; → marks a link to another table.

watch_events5 columns · 26 rows
idinteger · keyviewer_idintegervideo_idintegerwatched_attextwatch_secondsinteger
1112025-01-01 10:00:00300
2122025-01-01 11:00:00450
3212025-01-02 12:00:00600
4332025-01-02 13:00:00120
5142025-01-02 14:00:00700

showing 5 of 26 rows

example

The idea in one query. Press Run to see what it returns; running examples never affects your progress.

example.sql
SELECT
  id,
  watch_seconds,
  NTILE(4) OVER( ORDER BY watch_seconds DESC,id) AS bucket
FROM watch_events;

Watch for: NTILE creates roughly equal row counts, not equal numeric ranges or tie-preserving ranks.

build it step by step

Each step changes one thing. Run them in order and watch the result change.

  1. Sort the values you will bucket. NTILE splits an ordered list into roughly equal buckets. Sort watch_seconds so bucket 1 holds the longest watches.

    step-1.sql
    SELECT id, watch_seconds
    FROM watch_events
    ORDER BY watch_seconds DESC, id
    LIMIT 12;
  2. Assign quartile buckets. NTILE(4) labels rows 1–4 over the ordered window. Bucket edges can differ slightly when counts do not divide evenly.

    step-2.sql
    SELECT
      id,
      watch_seconds,
      NTILE(4) OVER(ORDER BY watch_seconds DESC, id) AS bucket
    FROM watch_events;

challenge 1

Return id, watch_seconds and bucket using NTILE(4), ordered within the window by watch_seconds descending then id.

Return idwatch_secondsbucketany row order

challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.