Example 1
Normalise three exam scores to z-scores
The three scores 10, 20, 30 have a mean of 20 and a sample standard deviation of 10. Alice's z-score is (10 − 20) / 10 = −1.0: one standard deviation below the mean. Bob's score equals the mean exactly, yielding 0.0. Carol is one standard deviation above, yielding 1.0. In practice you would add PARTITION BY group_col inside the OVER() clauses to compute separate z-scores within each group — for example, per subject or per exam sitting. Replace STDDEV_SAMP with STDDEV_POP (or STDEVP in SQL Server) if the dataset represents the full population rather than a sample.
CREATE TABLE test_scores (student VARCHAR(20), score INT);
INSERT INTO
test_scores
VALUES
('Alice', 10),
('Bob', 20),
('Carol', 30);SELECT
student,
score,
(score - AVG(score * 1.0) OVER ()) / STDDEV_SAMP(score) OVER () AS z_score
FROM
test_scores
ORDER BY
score;| student | score | z_score |
|---|---|---|
| Alice | 10 | -1 |
| Bob | 20 | 0 |
| Carol | 30 | 1 |
CREATE TABLE test_scores (student VARCHAR(20), score INT);
INSERT INTO
test_scores
VALUES
('Alice', 10),
('Bob', 20),
('Carol', 30);SELECT
student,
score,
(score - AVG(score * 1.0) OVER ()) / STDEV (score) OVER () AS z_score
FROM
test_scores
ORDER BY
score;| student | score | z_score |
|---|---|---|
| Alice | 10 | -1 |
| Bob | 20 | 0 |
| Carol | 30 | 1 |
CREATE TABLE test_scores (student VARCHAR(20), score INT);
INSERT INTO
test_scores
VALUES
('Alice', 10),
('Bob', 20),
('Carol', 30);WITH
stats AS (
SELECT
AVG(score * 1.0) AS mean_score,
SQRT(
(
SUM(score * score) - SUM(score) * SUM(score) * 1.0 / COUNT(*)
) / (COUNT(*) - 1)
) AS stddev_score
FROM
test_scores
)
SELECT
t.student,
t.score,
(t.score - s.mean_score) / s.stddev_score AS z_score
FROM
test_scores t,
stats s
ORDER BY
t.score;| student | score | z_score |
|---|---|---|
| Alice | 10 | -1 |
| Bob | 20 | 0 |
| Carol | 30 | 1 |
SQL Server uses STDEV() instead of STDDEV_SAMP(). SQLite requires a CTE-based workaround since it has no built-in standard deviation function.