Вы можете использовать полусоединение EXISTS
для идентификации кандидатов:
Выберите нужные строки:
SELECT * FROM tbl
WHERE NOT EXISTS (
SELECT *
FROM tbl t
WHERE t.col1 = tbl.col1
AND t.id = tbl.id - 1
)
ORDER BY id
Избавьтесь от ненужных строк:
DELETE FROM tbl
-- SELECT * FROM tbl
WHERE EXISTS (
SELECT *
FROM tbl t
WHERE t.col1 = tbl.col1
AND t.id = tbl.id - 1
)
Это эффективно удаляет каждую строку, где предыдущая строка имеет одинаковое значение в col1
, тем самым достигая поставленной цели: выживает только первая строка каждого пакета.
Я оставил прокомментированный оператор SELECT
, потому что вы должны всегда проверять, что будет удалено, прежде чем вы сделаете это.
Решение для непоследовательных идентификаторов:
Если ваша СУБД поддерживает оконные функции CTE и (например, PostgreSQL, Oracle, SQL Server, ... но не SQLite, MS Access или MySQL ), есть элегантный способ:
WITH x AS (
SELECT *, row_number() OVER (ORDER BY id) AS rn
FROM tbl
)
SELECT id, col1
FROM x
WHERE NOT EXISTS (
SELECT *
FROM x x1
WHERE x1.col1 = x.col1
AND x1.rn = x.rn - 1
)
ORDER BY id;
Существует также не очень элегантный способ сделать работу без этих тонкостей .
Должно работать на вас:
SELECT id, col1
FROM tbl
WHERE (
SELECT t.col1 = tbl.col1
FROM tbl AS t
WHERE t.id < tbl.id
ORDER BY id DESC
LIMIT 1) IS NOT TRUE
ORDER BY id
Инструмент для непоследовательных идентификаторов в тестовом корпусе
(протестировано в PostgreSQL)
CREATE TEMP TABLE tbl (id int, col1 int);
INSERT INTO tbl VALUES
(1,6050000),(2,6050000),(6,6050000)
,(14,6060000),(15,6060000),(16,6060000)
,(17,6060000),(18,6060000),(19,6050000)
,(20,6000000),(111,6000000);