sqlcmd.net validated sql reference
advanced windowing MySQL MariaDB SQL Server PostgreSQL SQLite

Calculate Relative Rank With PERCENT_RANK And CUME_DIST

Use percent-rank window functions to express each row's position within an ordered group.

Docker-validated Not currently validation-green

Show relative rank for each test score

Dan is first in ascending score order, so his percent rank is 0. Bob and Carol tie at 80 and share the same rank values. Ada is last and reaches the top of the cumulative distribution.

MySQL SQL Server PostgreSQL
Engine-specific syntax
Setup
CREATE TABLE scores (student VARCHAR(20), score INT);

INSERT INTO
  scores
VALUES
  ('Ada', 95),
  ('Bob', 80),
  ('Carol', 80),
  ('Dan', 60);
SQL
SELECT
  student,
  score,
  PERCENT_RANK() OVER (
    ORDER BY
      score
  ) AS pct_rank,
  CUME_DIST() OVER (
    ORDER BY
      score
  ) AS cumulative_dist
FROM
  scores
ORDER BY
  score,
  student;
studentscorepct_rankcumulative_dist
Dan6000.25
Bob800.33333333333333330.75
Carol800.33333333333333330.75
Ada9511
MariaDB
Engine-specific syntax
Setup
CREATE TABLE scores (student VARCHAR(20), score INT);

INSERT INTO
  scores
VALUES
  ('Ada', 95),
  ('Bob', 80),
  ('Carol', 80),
  ('Dan', 60);
SQL
SELECT
  student,
  score,
  PERCENT_RANK() OVER (
    ORDER BY
      score
  ) AS pct_rank,
  CUME_DIST() OVER (
    ORDER BY
      score
  ) AS cumulative_dist
FROM
  scores
ORDER BY
  score,
  student;
studentscorepct_rankcumulative_dist
Dan6000.25
Bob800.33333333330.75
Carol800.33333333330.75
Ada9511
SQLite
Engine-specific syntax
Setup
CREATE TABLE scores (student TEXT, score INT);

INSERT INTO
  scores
VALUES
  ('Ada', 95),
  ('Bob', 80),
  ('Carol', 80),
  ('Dan', 60);
SQL
SELECT
  student,
  score,
  PERCENT_RANK() OVER (
    ORDER BY
      score
  ) AS pct_rank,
  CUME_DIST() OVER (
    ORDER BY
      score
  ) AS cumulative_dist
FROM
  scores
ORDER BY
  score,
  student;
studentscorepct_rankcumulative_dist
Dan6000.25
Bob800.33333333333333330.75
Carol800.33333333333333330.75
Ada9511

Floating-point formatting can vary slightly by engine, so expected rows are not fixed here.

Where this command helps.

  • showing where a score sits within a distribution
  • labeling rows by relative standing rather than absolute rank

What the command is doing.

PERCENT_RANK() and CUME_DIST() turn an ordered position into a fractional value between 0 and 1. PERCENT_RANK reports how far a row's rank is from the first row relative to the partition size. CUME_DIST reports the cumulative fraction of rows less than or equal to the current row's sort value. They are useful for percentile-like labels, leaderboards, and distribution analysis.