Может быть быстрым кодом, так как отсчет не требуется.
Тест в реальном времени: https://www.db -fiddle.com / f / dBdH9tZd4W6Eac1TCRXZ8U / 0
select *
from tbl outr
where not exists
(
select 1 / 0 -- just a proof that this is not evaluated. won't cause division by zero
from tbl inr
where
inr.id <> outr.id
and right(inr.value, 6) = right(outr.value, 6)
)
Выход:
| id | value |
| --- | --------------- |
| 2 | aaaaaaaaaaaaaa |
| 4 | aaaaaaaaaaaaaaB |
| 5 | Hello |
Логика состоит в том, чтобы проверять другие строки, которые не равны тому же id внешней строки. Если эти другие строки имеют те же правые 6 символов, что и внешняя строка, не отображайте эту внешнюю строку.
UPDATE
Я неправильно понял намерение ОП. Это обратное. В любом случае, просто поменяйте логику. Используйте EXISTS вместо NOT EXISTS
Тест в реальном времени: https://www.db -fiddle.com / f / dBdH9tZd4W6Eac1TCRXZ8U / 3
select *
from tbl outr
where exists
(
select 1 / 0 -- just a proof that this is not evaluated. won't cause division by zero
from tbl inr
where
inr.id <> outr.id
and right(inr.value, 6) = right(outr.value, 6)
)
Выход:
| id | value |
| --- | ----------- |
| 1 | abcdePuzzle |
| 3 | abcPuzzle |
UPDATE
Протестировал запрос. Производительность моего ответа (коррелированный EXISTS
подход) не является оптимальной. Просто держу мой ответ, чтобы другие знали, какого подхода избегать:)
GhostGambler ответ быстрее, чем correlated EXISTS
подход. Для 5 миллионов строк его ответ занимает всего 2,762 секунды:
explain analyze
SELECT
tbl.*
FROM
(
SELECT
RIGHT(value, 6) AS ending
FROM
tbl
GROUP BY
ending
HAVING
COUNT(*) > 1
) grouped
JOIN tbl ON grouped.ending = RIGHT(value, 6)

Мой ответ (коррелированный EXISTS
) занимает 4,08 секунды:
explain analyze
select *
from tbl outr
where exists
(
select 1 / 0 -- just a proof that this is not evaluated. won't cause division by zero
from tbl inr
where
inr.id <> outr.id
and right(inr.value, 6) = right(outr.value, 6)
)

Простой запрос - самый быстрый, без объединения, просто простой запрос IN. 2,722 секунды. Он имеет практически такую же производительность, что и подход JOIN, поскольку у них один и тот же план выполнения. Это ответ от kiks73 . Я просто не знаю, почему он сделал второй ответ излишне сложным.
Так что это просто дело вкуса или выбор кода, который будет более читабельным select from in
против select from join
explain analyze
SELECT *
FROM tbl
where right(value, 6) in
(
SELECT
RIGHT(value, 6) AS ending
FROM
tbl
GROUP BY
ending
HAVING
COUNT(*) > 1
)
Результат:

<Ч />
Используемые данные испытаний:
CREATE TABLE tbl (
id INTEGER primary key,
value VARCHAR(20)
);
INSERT INTO tbl
(id, value)
VALUES
('1', 'abcdePuzzle'),
('2', 'aaaaaaaaaaaaaa'),
('3', 'abcPuzzle'),
('4', 'aaaaaaaaaaaaaaB'),
('5', 'Hello');
insert into tbl(id, value)
select x.y, 'Puzzle'
from generate_series(6, 5000000) as x(y);
create index ix_tbl__right on tbl(right(value, 6));
<Ч />
Спектакли без указателя и с указателем на tbl(right(value, 6))
:
JOIN
подход:
Без индекса: 3,805 секунды
С индексом: 2,762 секунды

IN
подход:
Без индекса: 3,719 секунд
С индексом: 2,722 секунды
