Ответ 1
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
FROM mytable t
)
WHERE rn > 1
У меня есть строки в таблице базы данных Oracle, которые должны быть уникальными для комбинации двух полей, но уникальный ограничитель не настроен в таблице, поэтому мне нужно найти все строки, которые сами нарушают ограничение, используя SQL. К сожалению, мои скудные навыки SQL не справляются с задачей.
Моя таблица имеет три столбца, которые имеют значение: entity_id, station_id и obs_year. Для каждой строки комбинация station_id и obs_year должна быть уникальной, и я хочу узнать, есть ли строки, которые нарушают это, очищая их SQL-запросом.
Я пробовал следующий SQL (предложенный этот предыдущий вопрос), но он не работает для меня (я получаю столбец ORA-00918 двусмысленно):
SELECT
entity_id, station_id, obs_year
FROM
mytable t1
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes
ON
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
Может кто-нибудь предложить, что я делаю неправильно, и/или как это решить?
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
FROM mytable t
)
WHERE rn > 1
SELECT entity_id, station_id, obs_year
FROM mytable t1
WHERE EXISTS (SELECT 1 from mytable t2 Where
t1.station_id = t2.station_id
AND t1.obs_year = t2.obs_year
AND t1.RowId <> t2.RowId)
Повторно написать запрос
SELECT
t1.entity_id, t1.station_id, t1.obs_year
FROM
mytable t1
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes
ON
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
Я думаю, что неоднозначная ошибка столбца (ORA-00918) заключалась в том, что вы были select
столбцами, имена которых отображались как в таблице, так и в подзапросе, но вы не указали, хотите ли вы ее от dupes
или от mytable
(с псевдонимом t1
).
Измените 3 поля в начальном выборе, чтобы быть
SELECT
t1.entity_id, t1.station_id, t1.obs_year
Не удалось создать новую таблицу, которая включает в себя уникальное ограничение, а затем скопировать данные по строке, игнорируя ошибки?
Вам нужно указать таблицу для столбцов основного выбора. Кроме того, предполагая, что entity_id является уникальным ключом для mytable и не имеет отношения к поиску дубликатов, вы не должны группировать его в подзапросах dupes.
Try:
SELECT t1.entity_id, t1.station_id, t1.obs_year
FROM mytable t1
INNER JOIN (
SELECT station_id, obs_year FROM mytable
GROUP BY station_id, obs_year HAVING COUNT(*) > 1) dupes
ON
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
FROM mytable t
)
WHERE rn > 1
Quassnoi является наиболее эффективным для больших таблиц. У меня был этот анализ стоимости:
SELECT a.dist_code, a.book_date, a.book_no
FROM trn_refil_book a
WHERE EXISTS (SELECT 1 from trn_refil_book b Where
a.dist_code = b.dist_code and a.book_date = b.book_date and a.book_no = b.book_no
AND a.RowId <> b.RowId)
;
дал стоимость 1322341
SELECT a.dist_code, a.book_date, a.book_no
FROM trn_refil_book a
INNER JOIN (
SELECT b.dist_code, b.book_date, b.book_no FROM trn_refil_book b
GROUP BY b.dist_code, b.book_date, b.book_no HAVING COUNT(*) > 1) c
ON
a.dist_code = c.dist_code and a.book_date = c.book_date and a.book_no = c.book_no
;
предоставила стоимость 1271699
while
SELECT dist_code, book_date, book_no
FROM (
SELECT t.dist_code, t.book_date, t.book_no, ROW_NUMBER() OVER (PARTITION BY t.book_date, t.book_no
ORDER BY t.dist_code) AS rn
FROM trn_refil_book t
) p
WHERE p.rn > 1
;
дал стоимость 1021984
Таблица не была проиндексирована....
SELECT entity_id, station_id, obs_year
FROM mytable
GROUP BY entity_id, station_id, obs_year
HAVING COUNT(*) > 1
Укажите поля для поиска дубликатов как для SELECT, так и для GROUP BY.
Работает с помощью GROUP BY
, чтобы найти любые строки, которые соответствуют любым другим строкам на основе указанных столбцов.
HAVING COUNT(*) > 1
говорит, что нас интересуют только любые строки, которые происходят более одного раза (и, следовательно, дублируются)
Я думал, что многие решения здесь были громоздкими и сложными для понимания, так как у меня было ограничение первичного ключа из 3 столбцов, и мне нужно было найти дубликаты. Так вот вариант
SELECT id, name, value, COUNT(*) FROM db_name.table_name
GROUP BY id, name, value
HAVING COUNT(*) > 1