SQL: Как найти дубликаты на основе двух полей? - PullRequest
20 голосов
/ 17 августа 2010

У меня есть строки в таблице базы данных 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

Может кто-нибудь подсказать, что я делаю неправильно, и /или как это решить?

Ответы [ 9 ]

38 голосов
/ 17 августа 2010
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
11 голосов
/ 17 августа 2010
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)
2 голосов
/ 17 августа 2010

Измените 3 поля в начальном выборе на

SELECT
t1.entity_id, t1.station_id, t1.obs_year
2 голосов
/ 17 августа 2010

Перезапись вашего запроса

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).

1 голос
/ 17 августа 2010

Вам необходимо указать таблицу для столбцов в главном меню. Кроме того, предполагая, что entity_id является уникальным ключом для mytable и не имеет отношения к поиску дубликатов, вам не следует группировать его в подзапросе dupes.

Попытка:

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
1 голос
/ 17 августа 2010

Не могли бы вы создать новую таблицу, содержащую ограничение уникальности, а затем копировать данные по строкам, игнорируя сбои?

0 голосов
/ 02 мая 2019

Я думал, что многие решения здесь были громоздкими и сложными для понимания, поскольку у меня было ограничение первичного ключа из 3 столбцов, и мне нужно было найти дубликаты.Так вот вариант

SELECT id, name, value, COUNT(*) FROM db_name.table_name
GROUP BY id, name, value
HAVING COUNT(*) > 1
0 голосов
/ 08 августа 2014
  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 говорит, что мы заинтересованы только в том, чтобы видеть строки, встречающиеся более 1 раза (и, следовательно, дубликаты)

0 голосов
/ 03 декабря 2013
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

, а

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

Таблица не была проиндексирована ....

...