BUG #19563: Planner does not eliminate redundant outer DISTINCT over UNION

Started by PG Bug reporting form5 days ago2 messagesbugs
Jump to latest
#1PG Bug reporting form
noreply@postgresql.org

The following bug has been logged on the website:

Bug reference: 19563
Logged by: cl hl
Email address: 2320415112@qq.com
PostgreSQL version: 17.10
Operating system: Linux LAPTOP-2SQAVLB0 6.6.87.2-microsoft-standard-
Description:

PostgreSQL keeps an extra duplicate-removal operator for a redundant outer
`DISTINCT` over a `UNION` query.

`UNION` already returns a distinct set of rows. Therefore, the following
transformation is semantically redundant:

```sql
SELECT a FROM t WHERE ...
UNION
SELECT a FROM t WHERE ...
```

to:

```sql
SELECT DISTINCT *
FROM (
SELECT a FROM t WHERE ...
UNION
SELECT a FROM t WHERE ...
) AS u;
```

However, PostgreSQL plans the mutated query with two `HashAggregate` nodes:
one for the `UNION` duplicate elimination and another for the outer
`DISTINCT`. The outer `HashAggregate` should be removable because its input
is already distinct on the same output columns.

How to repeat

```sql
DROP TABLE IF EXISTS outer_distinct_union_t;

CREATE TABLE outer_distinct_union_t (
a INT PRIMARY KEY,
b INT
);

INSERT INTO outer_distinct_union_t
SELECT i, i % 10
FROM generate_series(1, 1000) AS g(i);

ANALYZE outer_distinct_union_t;

-- Original query.
-- UNION already removes duplicates.
EXPLAIN
SELECT a
FROM outer_distinct_union_t
WHERE a <= 800
UNION
SELECT a
FROM outer_distinct_union_t
WHERE a >= 200;

-- Mutated query.
-- The outer DISTINCT is redundant.
EXPLAIN
SELECT DISTINCT *
FROM (
SELECT a
FROM outer_distinct_union_t
WHERE a <= 800
UNION
SELECT a
FROM outer_distinct_union_t
WHERE a >= 200
) AS u;
```

#2Vik Fearing
vik@postgresfriends.org
In reply to: PG Bug reporting form (#1)
Re: BUG #19563: Planner does not eliminate redundant outer DISTINCT over UNION

On 21/07/2026 12:46, PG Bug reporting form wrote:

The following bug has been logged on the website:

Bug reference: 19563
Logged by: cl hl
Email address: 2320415112@qq.com
PostgreSQL version: 17.10
Operating system: Linux LAPTOP-2SQAVLB0 6.6.87.2-microsoft-standard-
Description:

PostgreSQL keeps an extra duplicate-removal operator for a redundant outer
`DISTINCT` over a `UNION` query.

Funny this should come up, I have recently been working on improvements
for DISTINCT tracking. Nothing ready to publish yet, but at least one
other person noticed this missed optimization, and others like it.

--

Vik Fearing