Выберите все похожие строки, которые являются возможными дубликатами, используя LIKE? - PullRequest
1 голос
/ 08 апреля 2011

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

songName в одной строке, аналогичной или равной songName в любой другой строке в той же таблице (Songs), а ArtistID одинаков в обеих строках. Это должно работать, не зная содержимого songName. Если я хочу сравнить известное название песни со всеми другими в базе данных, это можно сделать с помощью «songName LIKE '% known name%'», но как мне найти все дубликаты без этого?

Пример таблицы композиций:

id  songName            artistID  duration
--------------------------------------------
0  This is a song       5         3:43
1  Another song         3         3:23
2  01-This is a song    5         3:42
3  song                 4         4:01
4  song                 4         6:33
5  Another record       2         2:45

Ожидаемые результаты:

id  songName            artistID  duration
--------------------------------------------
0   This is a song      5         3:43
2   01-This is a song   5         3:42
3   song                4         4:01
4   song                4         6:33

EDIT:

Поскольку была предложена идея создания хеша и сравнения их, я думаю об использовании этой псевдо-функции для создания хеша для каждого названия песни:

Public Function createHash(ByVal phrase As String) As String
    'convert to lower case
    phrase = LCase(phrase)

    'split the phrase into words
    Dim words() As String = phrase.Replace("_", " ").Split(" ")

    Dim hash As String = ""
    For w = 0 To words.Count - 1
        'remove noise words (a, an, the, etc.)
        words(w) = removeNoiseWords(words(w))
        'convert 1 or 2-digit numbers to corresponding words
        words(w) = number2word(words(w))
    Next

    'rebuild using replaced words and remove spaces
    hash = String.Join("", words)

    'convert upper ascii into alphabetic (ie. ñ = n, Ö = O, etc.)
    hash = removeUnsupChars(hash, True)

    'strip away all remaining non-alphanumeric characters
    hash = REGEX_Replace(hash, "[^A-Za-z0-9]", "")
    Return hash
End Function

Как только хеш будет вычислен, я сохраню его для каждой записи, а затем выберу дубликаты, используя количество (хеш)> 1. Затем я буду использовать .NET-код, чтобы увидеть, является ли artistID одинаковым для возвращенных записей.

Похоже, это решение пока работает нормально. Вот оператор SQLite, который я использую, чтобы найти дубликаты песен:

SELECT count(*),hash from Songs GROUP BY hash HAVING count(hash) > 1 ORDER BY hash;

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

    For i = 0 To dupeHashes.Count - 1
        SQLconnect.Open()
        SQLcommand = SQLconnect.CreateCommand
        SQLcommand.CommandText = "SELECT * from Songs WHERE hash = '" & dupeHashes(i) & "';"
        SQLreader = SQLcommand.ExecuteReader()
        While SQLreader.Read()
            'get whatever data needed for each duplicate song
        End While
        SQLcommand.Dispose()
        SQLconnect.Close()
    Next

Ответы [ 2 ]

2 голосов
/ 09 апреля 2011

Лично я бы добавил дополнительное поле, в котором вы вычисляете некий «хэш» заголовка.Хорошей функцией для этого будет удаление каждого не алфавитного символа, включая пробелы, удаление любой статьи (например, «the», «a», «an»), а затем вычисление кода soundex для заголовка идобавив префикс к строке artistId.

Таким образом, в вашем случае вы получите:

id  songName            artistID  duration  Hash
----------------------------------------------------
0  This is a song       5         3:43      5.T0021
1  Another song         3         3:23      3.A9872
2  01-This is a song    5         3:42      5.T0021
3  song                 4         4:01      4.S0332
4  song                 4         6:33      4.S0332
5  Another record       2         2:45      2.A7622

Отныне получение только строк, имеющих ... count (Hash)> 1, должно бытьпросто ...

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

0 голосов
/ 08 апреля 2011

Можно получить краткое представление о вопросе, но необходимо уточнить один момент: почему результата нету 1 Другая песня 3 3:23 запись? так как это может рассматриваться как дубликат с этими 3 песня 4 4:01 4 песня 4 6:33 записи

Я просто пишу простой скрипт в tsql, чтобы решить, эффективность низкая, просто проверьте в качестве справки.

 drop table #t;
drop table #result;

create table #t 
(
id int ,
songName varchar(100),
artistID int,
duration varchar(20)
)
insert into #t
select '0',  'This is a song'   ,    '5'  ,       '3:43' union all
select '1',  'Another song'     ,    '3'  ,       '3:23' union all
select '2',  '01-This is a song',    '5'  ,       '3:42' union all
select '3',  'song'             ,    '4'  ,       '4:01' union all
select '4',  'song'             ,    '4'  ,       '6:33' union all
select '5',  'Another record'   ,    '2'  ,       '2:45'

select * from #t
select * into #result from #t where 1 = 0

declare @sName varchar(100)
declare @id int
declare @count int

declare c cursor for 
select id, songName from #t

open c
fetch next from c into @id, @sName
while @@FETCH_STATUS = 0
begin
    select @count = COUNT(*) from #result where id = @id
    if @count = 0 
    begin
        select @count = COUNT(*) from #t where songName like '%'+@sName+'%'
        --select @count , @sName
        if @count > 1
        begin
            insert into #result select *  from #t where songName like '%'+@sName+'%' and id not in (select id from #result)
        end
    end
fetch next from c into @id, @sName
end
close c
deallocate c

select * from #result 
...