PostgreSQL DISTINCT Usages
Use PostgreSQL SELECT DISTINCT to remove duplicate rows, or DISTINCT ON with ORDER BY to keep a chosen row from each group.
PostgreSQL SELECT DISTINCT removes duplicate rows from the result. PostgreSQL also supports DISTINCT ON, which keeps the first row in each group; use ORDER BY to control which row comes first.
PostgreSQL DISTINCT syntax
To return a result set with no duplicate rows, use the SELECT statement with the DISTINCT keyword:
Here is the syntax for DISTINCT:
SELECT
DISTINCT column1 [, column2, ...]
FROM
table_name;
Explanation:
- The keyword
DISTINCTshould be specified afterSELECT. - Specify the columns to evaluate for duplicates after the
DISTINCTkeyword . - Separate multiple column names with commas. PostgreSQL removes rows that have the same values in every selected expression; it does not concatenate the values.
DISTINCT *compares whole output rows, including every selected column.
PostgreSQL also provides DISTINCT ON (expression) to keep the first row of each set of duplicates using the following syntax:
SELECT
DISTINCT ON (column1) column_alias,
column2
FROM
table_name
ORDER BY
column1,
column2;
Use the ORDER BY clause with DISTINCT ON (expression) to control which row is kept from each group. Without a suitable ordering, the chosen row is unpredictable.
The DISTINCT ON expressions must match the leftmost ORDER BY expressions. Additional sort expressions can specify which row has precedence within each group.
PostgreSQL DISTINCT Examples
We will use the tables in the Sakila sample database for demonstration, please install the Sakila sample database in PostgreSQL first.
Unless a query specifies ORDER BY, PostgreSQL does not guarantee the order of its result rows; the output tables below show one possible order.
To retrieve all ratings of films from the film table, use the following statement:
SELECT
DISTINCT rating
FROM
film;
rating
--------
R
PG-13
G
PG
NC-17
(5 rows)Here, in order to find all the films ratings, we use DISTINCT rating, so that each film rating appears only once in the result set.
To retrieve all rent amounts from the film table, use the following statement:
SELECT
DISTINCT rental_rate
FROM
film;
rental_rate
-------------
2.99
4.99
0.99
(3 rows)Here, in order to find all the film rental amounts, we use DISTINCT rental_rate, so that each film rental amount appears only once in the result set.
To retrieve all combinations of ratings and rental amounts from the film table, use the following statement:
SELECT
DISTINCT rating, rental_rate
FROM
film
ORDER BY rating;
rating | rental_rate
--------+-------------
G | 0.99
G | 4.99
G | 2.99
PG | 2.99
PG | 0.99
PG | 4.99
PG-13 | 4.99
PG-13 | 0.99
PG-13 | 2.99
R | 0.99
R | 2.99
R | 4.99
NC-17 | 0.99
NC-17 | 2.99
NC-17 | 4.99
(15 rows)Here, DISTINCT rating, rental_rate returns each combination once. The query orders by rating, but the order of rental_rate values within each rating is unspecified because it is not included in ORDER BY.
If you want to return the first row for each set of films ratings, use the DISTINCT ON:
SELECT
DISTINCT ON (rating) rating,
film_id,
title
FROM
film
ORDER BY rating, film_id DESC;
rating | film_id | title
--------+---------+------------------
G | 2 | ACE GOLDFINGER
PG | 1 | ACADEMY DINOSAUR
PG-13 | 7 | AIRPLANE SIERRA
R | 8 | AIRPORT POLLOCK
NC-17 | 3 | ADAPTATION HOLESDISTINCT and NULL
For duplicate elimination, PostgreSQL treats NULL values as equal, so duplicate rows that contain NULL in the same output positions collapse to one row.
For example the following SQL statement returns multiple rows of NULL records:
SELECT NULL nullable_col
UNION ALL
SELECT NULL nullable_col
UNION ALL
SELECT NULL nullable_col;
nullable_col
--------------
<null>
<null>
<null>
(3 rows)Here, we have 3 rows, each of which has a nullable_col column value of NULL.
After using DISTINCT:
SELECT
DISTINCT nullable_col
FROM
(
SELECT NULL nullable_col
UNION ALL
SELECT NULL nullable_col
UNION ALL
SELECT NULL nullable_col
) t;
nullable_col
--------------
<null>
(1 row)This example uses to UNION ALL simulate a recordset containing multiple NULL values.
Conclusion
Use DISTINCT to remove duplicate output rows and DISTINCT ON to select one ordered row from each group:
- The
SELECT DISTINCTstatement returns a result set with no duplicate rows. - You can specify one or more expressions after
DISTINCT, or useDISTINCT *for whole rows. DISTINCTcollapses duplicate rows, including rows with matchingNULLpositions.DISTINCT ONkeeps one row per group, andORDER BYdetermines which row comes first.
For the complete syntax and processing rules, see PostgreSQL’s SELECT reference.