Поиск идентификаторов повторяющихся записей sql

У меня есть таблица, в которой много повторяющихся записей, а именно tbl_voter с идентификатором в качестве первичного ключа, автоматическое увеличение. и есть еще одна таблица tbl_notes, в которой есть заметки для каждого избирателя. tbl_notes может иметь ноль или более записей о каждом избирателе. Идентификатор из tbl_voter — это внешний ключ в файле tbl_notes.

Проблема в том, что, поскольку в таблице избирателей есть дубликаты, в таблице заметок также есть дубликаты.

Например: tbl_voter

ID    Name    Address
01    abc     xyz
02    def     pqr
03    abc     xyz
04    abc     xyz
05    abc     xyz
06    def     pqr

tbl_notes

Noteid    ID     Note
A001      01     aaaaaa
A002      02     bbbbbb
A003      01     cccccc
A004      03     dddddd
A005      03     eeeeee
A006      04     ffffff
A007      05     gggggg
A008      01     hhhhhh

Я хочу найти все идентификаторы оригинальных и их дубликатов, чтобы обновить tbl_notes

Например: tbl_voter

ID    Name    Address
01    abc     xyz
02    def     pqr

tbl_notes

Noteid    ID     Note
A001      01     aaaaaa
A002      02     bbbbbb
A003      01     cccccc
A004      01     dddddd
A005      01     eeeeee
A006      01     ffffff
A007      01     gggggg
A008      01     hhhhhh

До сих пор я пытался найти дубликаты записей, но это дает мне как оригинальные, так и дубликаты. Мне нужен запрос, который возвращает меня:

RealID     DuplicateID
01         03
01         04
01         05
02         06

Запрос, который я пробовал:

select *
from tbl_voter a inner join 
(
select id,firstname,lastname,zip,housenumber,COUNT(*) AS dupes  from tbl_voter
where riding = '35019'
group by
firstname,lastname,zip,housenumber
having count(*) > 1 
) b on a.firstname = b.firstname
and a.lastname = b.lastname
and a.zip = b.zip
and a.firstname is not null
and b.firstname is not null
and a.riding='35019'
and a.housenumber=b.housenumber
order by a.firstname asc

Если я добавлю идентификатор в запрос выбора, он выдает ошибку, говорящую о том, что идентификатор не может использоваться в группе по запросу, что правильно, поскольку идентификаторы будут все время разными.

Запрос с учетом идентификаторов:

select a.id as realid, b.id as dupid, a.firstname,a.lastname,a.zip,a.housenumber
from tbl_voter a inner join 
(
select id,firstname,lastname,zip,housenumber,COUNT(*) AS dupes  from tbl_voter
where riding = '35019'
group by
id,firstname,lastname,zip,housenumber
having count(*) > 1 
) b on a.firstname = b.firstname
and a.lastname = b.lastname
and a.zip = b.zip
and a.firstname is not null
and b.firstname is not null
and a.riding='35019'
and a.housenumber=b.housenumber
order by a.firstname asc

Если я получу дубликаты и настоящие идентификаторы, я могу обновить файл tbl_notes.

Спасибо, Шашанк


person Shashank    schedule 08.07.2014    source источник
comment
Я не могу вспомнить точный синтаксис, но я думаю, что GROUP_CONCAT можно использовать для предоставления всех идентификаторов, где строка, столбец = строка, идентификатор столбца начинается с поиска этого   -  person andrew    schedule 08.07.2014
comment
@andrew Group_concat не работает для MSSQL. Я пытался искать альтернативы, но в основном он предлагает сгруппировать идентификатор и не возвращать дубликаты. Мне нужны дубликаты, чтобы обновить их в обеих таблицах.   -  person Shashank    schedule 08.07.2014


Ответы (2)


Я собираюсь сосредоточиться только на поиске таблицы с настоящим идентификатором и дубликатами идентификаторов. На базовом уровне вы пытаетесь найти все пары идентификаторов, в которых информация дублируется. По сути, мы можем начать с этой таблицы:

RealID     DuplicateID
01         01
01         03
01         04
01         05
03         01
03         03
03         04
03         05
04         01
04         03
04         04
04         05
05         01
05         03
05         04
05         05
02         02
02         06
06         02
06         06

Теперь это гораздо больше информации, чем вам нужно, но представление о вашей таблице таким образом значительно упрощает запрос. Вы хотите создать самообъединение в tbl_voter, где все данные без идентификатора совпадают.

Далее, давайте отфильтруем большую часть информации. Просто указав, что realID должен быть меньше DuplicateID, вы удалите много ненужной информации. Тогда ваша таблица выглядит так:

RealID     DuplicateID
01         03
01         04
01         05
03         04
03         05
04         05
02         06

Это все еще лишняя информация, но уже не такая большая. Последнее, что вы можете сделать, чтобы избавиться от лишней информации, — это сгруппировать по повторяющемуся идентификатору и выбрать минимальный (реальный идентификатор). Это даст вам стол, который вы ищете. Этот запрос выглядит следующим образом:

Select min(v.id) as RealID, v2.id as DuplicateId
From tbl_voter v join tbl_voter v2
    on v.firstname = v2.firstname
    and v.lastname = v2.lastname
    and v.zip = v2.zip
    and v.firstname is not null
    and v2.firstname is not null
    and v.riding='35019'
    and v.riding = v2.riding
    and v.housenumber=v2.housenumber
    and v.id < v2.id
Group by v2.id
person Jenn    schedule 08.07.2014
comment
Потрясающий ответ, я пытался сделать это сам, я знал, что где-то понадобится внутреннее соединение - person CSharper; 08.07.2014
comment
Хорошо объяснил! Отличный ответ! Работал как прелесть! :) Спасибо Дженн! - person Shashank; 08.07.2014
comment
@Jenn Будет ли этот запрос также учитывать нулевые значения? Я имею в виду, если имя и фамилия равны, а значения почтового индекса равны нулю, будет ли оно соответствовать им или нет? Можете ли вы помочь мне сформулировать запрос, который делает то же самое? Спасибо! - person Shashank; 14.07.2014
comment
@Shashank Если оба значения zip равны нулю, этот запрос будет работать. Тем не менее, я предполагаю, что дубликаты записей будут из-за того, что кто-то зарегистрировался дважды и, возможно, во второй раз они не указали свой почтовый индекс. В этом случае они не будут соответствовать им, но вы можете сделать что-то вроде and (v.zip = v1.zip or v.zip is null or v2.zip is null) - person Jenn; 14.07.2014
comment
Идеальный! Спасибо @Дженн - person Shashank; 14.07.2014

Вы можете попробовать создать ROW_NUMBER/RANK на основе ваших ключевых столбцов (а не столбцов с автоматическим приращением) и выбрать все записи, у которых row_number = 1. Что-то вроде того, что ниже

ВЫБЕРИТЕ id,имя,фамилию,zip,номер дома из (SELECT id,имя,фамилия,zip,номер дома, ROW_NUMBER()OVER(РАЗДЕЛЕНИЕ ПО id,имя,фамилия,zip,номер дома ORDER BY id,имя,фамилия,zip,номер дома ) как rowNumber FROM tbl_voter) ГДЕ rowNumber=1

person Raman    schedule 08.07.2014
comment
Не работает приятель, пишет ошибка рядом с предложением Where! :( - person Shashank; 08.07.2014
comment
@Shashank Не могли бы вы сообщить мне базу данных и версию? - person Raman; 08.07.2014