복붙노트

[SQL] 유사한 문자열을 포함하는 SQL 기록을 찾기

SQL

유사한 문자열을 포함하는 SQL 기록을 찾기

500.000 기록을 통해 들어있는 ID와 제목 : 나는 다음과 같은 2 열이있는 테이블이 있습니다. 예를 들면 :

ID  Title
--  ------------------------
1   Aliens
2   Aliens (1986)
3   Aliens vs Predator
4   Aliens 2
5   The making of "Aliens"

나는 매우 유사한 레코드를 찾을 필요가 있고, 내 말 것을에 의해 그들은 일반적으로이 차이는 제목의 끝에 3-6 문자에 의해 다릅니다. 나는 어떤 레코드를 반환하는 쿼리를 디자인해야합니다 그래서. 1, 2, 4 이미 levenstein 거리에서 보았다하지만 난 그것을 적용하는 방법을 모르겠어요. 또한 때문에 레코드 수의 쿼리는 밤새을해서는 안된다.

어떤 아이디어 나 제안을 주셔서 감사합니다

해결법

  1. ==============================

    1.당신이 정말로 당신이 당신의 질문에 공식화하는 정확한 방법으로 유사성을 정의 할 경우에 당신은 것입니다 - 당신이 말하는대로 - Levensthein 거리 계산을 구현해야합니다. 어느 쪽의 코드에 의해 또는 DataReader가 SQL 서버 기능으로 검색된 각 행 계산.

    당신이 정말로 당신이 당신의 질문에 공식화하는 정확한 방법으로 유사성을 정의 할 경우에 당신은 것입니다 - 당신이 말하는대로 - Levensthein 거리 계산을 구현해야합니다. 어느 쪽의 코드에 의해 또는 DataReader가 SQL 서버 기능으로 검색된 각 행 계산.

    언급 한 문제는 당신이 두 개의 문자열 사이의 상호 공유 요소가있을 수 있습니다 알고 가정 할 수 있기 때문에, 첫눈에 나타날 수보다 실제로 더 까다 롭습니다.

    그래서 Levenshtein 거리뿐만 아니라 당신은 아마도 (체결 효율적인 유사성 위해) 실제로 일치 할 필요가 연속 된 문자의 최소 수를 지정합니다.

    요약하면 : 그것은 지나치게 복잡하고 많은 시간이 소요 / 느린 방법처럼 들린다.

    흥미롭게도, SQL Server 2008의이 같은 것을 사용할 수있다 차이 기능을 가지고있다.

    두 개의 스트링의 음성 값을 평가하고 그 차이를 계산한다. 당신이 그런는 공백이나 숫자와 문자열의 시작 부분에 그림을 그리 듯 너무 많은 강조를 잘 처리하지 않기 때문에 영화 제목으로 여러 단어로 표현 제대로 작동하도록한다면 나는 확실 해요,하지만 여전히 재미있다 알고 있어야 술어.

    당신이 실제로 설명하려고하는 것은 검색 기능의 일종 인 경우에, 당신은 SQL 서버의 전체 텍스트 검색 기능을 조사해야한다 2008 그것은 내장을 제공 동의어 사전 지원, 멋진 SQL 술어와 "최고의 경기"에 대한 순위 메커니즘

    편집 : 당신은 중복을 제거하기 위해 찾고 있다면 아마 당신은 SSIS 퍼지 조회 및 퍼지 그룹 변환에 볼 수 있었다. 나는이에게 자신을 시도하지 않은, 그러나 그것은 약속 리드처럼 보인다.

    EDIT2 : 당신이 SSIS에 파고 여전히 Levensthein 거리 알고리즘의 성능과 투쟁하지 않으려면, 당신은 아마도 덜 복잡한 것 같습니다이 알고리즘을 시도 할 수 있습니다.

  2. ==============================

    2.대답으로 이미 표시되어 비록 모든 Google 직원에서이 질문에 그 실행은, 나는이에 도움이되는 몇 가지 코드를 공유하는 것이 생각. 당신의 SQL Server에서 CLR 사용자 정의 기능을 할 수있는 좋은 방법입니다 수 당신이 경우에, 당신은 당신에게 dbo.GetSimilarityScore라는 '유사성 점수'() 제공하는 기능이 생성에서 다음 자신의 Levensthein 거리 알고리즘을 구현할 수 있습니다. 나는 뒤죽박죽 단어 순서 및 영숫자가 아닌 문자에 많은 무게를하지 않고, 내 점수 케이스 - 무감각을 기반으로했습니다. 필요에 따라 당신은 당신의 점수 알고리즘을 조정할 수 있지만, 이것은 좋은 시작이다. 저를 얻기 위해이 코드 프로젝트에 링크 된 신용 시작했다.

    대답으로 이미 표시되어 비록 모든 Google 직원에서이 질문에 그 실행은, 나는이에 도움이되는 몇 가지 코드를 공유하는 것이 생각. 당신의 SQL Server에서 CLR 사용자 정의 기능을 할 수있는 좋은 방법입니다 수 당신이 경우에, 당신은 당신에게 dbo.GetSimilarityScore라는 '유사성 점수'() 제공하는 기능이 생성에서 다음 자신의 Levensthein 거리 알고리즘을 구현할 수 있습니다. 나는 뒤죽박죽 단어 순서 및 영숫자가 아닌 문자에 많은 무게를하지 않고, 내 점수 케이스 - 무감각을 기반으로했습니다. 필요에 따라 당신은 당신의 점수 알고리즘을 조정할 수 있지만, 이것은 좋은 시작이다. 저를 얻기 위해이 코드 프로젝트에 링크 된 신용 시작했다.

    Option Explicit On
    Option Strict On
    Option Compare Binary
    Option Infer On
    
    Imports System
    Imports System.Collections.Generic
    Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Data.SqlTypes
    Imports System.Text
    Imports System.Text.RegularExpressions
    Imports Microsoft.SqlServer.Server
    
    Partial Public Class UserDefinedFunctions
    
        Private Const Xms As RegexOptions = RegexOptions.IgnorePatternWhitespace Or RegexOptions.Multiline Or RegexOptions.Singleline
        Private Const Xmsi As RegexOptions = Xms Or RegexOptions.IgnoreCase
    
        ''' <summary>
        ''' Compute the distance between two strings.
        ''' </summary>
        ''' <param name="s1">The first of the two strings.</param>
        ''' <param name="s2">The second of the two strings.</param>
        ''' <returns>The Levenshtein cost.</returns>
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function ComputeLevenstheinDistance(ByVal string1 As SqlString, ByVal string2 As SqlString) As SqlInt32
            If string1.IsNull OrElse string2.IsNull Then Return SqlInt32.Null
            Dim s1 As String = string1.Value
            Dim s2 As String = string2.Value
    
            Dim n As Integer = s1.Length
            Dim m As Integer = s2.Length
            Dim d As Integer(,) = New Integer(n, m) {}
    
            ' Step 1
            If n = 0 Then Return m
            If m = 0 Then Return n
    
            ' Step 2
            For i As Integer = 0 To n
                d(i, 0) = i
            Next
    
            For j As Integer = 0 To m
                d(0, j) = j
            Next
    
            ' Step 3
            For i As Integer = 1 To n
                'Step 4
                For j As Integer = 1 To m
                    ' Step 5
                    Dim cost As Integer = If((s2(j - 1) = s1(i - 1)), 0, 1)
    
                    ' Step 6
                    d(i, j) = Math.Min(Math.Min(d(i - 1, j) + 1, d(i, j - 1) + 1), d(i - 1, j - 1) + cost)
                Next
            Next
            ' Step 7
            Return d(n, m)
        End Function
    
        ''' <summary>
        ''' Returns a score between 0.0-1.0 indicating how closely two strings match.  1.0 is a 100%
        ''' T-SQL equality match, and the score goes down from there towards 0.0 for less similar strings.
        ''' </summary>
        <Microsoft.SqlServer.Server.SqlFunction()> _
        Public Shared Function GetSimilarityScore(string1 As SqlString, string2 As SqlString) As SqlDouble
            If string1.IsNull OrElse string2.IsNull Then Return SqlInt32.Null
    
            Dim s1 As String = string1.Value.ToUpper().TrimEnd(" "c)
            Dim s2 As String = string2.Value.ToUpper().TrimEnd(" "c)
            If s1 = s2 Then Return 1.0F ' At this point, T-SQL would consider them the same, so I will too
    
            Dim score1 As SqlDouble = InternalGetSimilarityScore(s1, s2)
            If score1.IsNull Then Return SqlDouble.Null
    
            Dim mod1 As String = GetSimilarityString(s1)
            Dim mod2 As String = GetSimilarityString(s2)
            Dim score2 As SqlDouble = InternalGetSimilarityScore(mod1, mod2)
            If score2.IsNull Then Return SqlDouble.Null
    
            If score1 = 1.0F AndAlso score2 = 1.0F Then Return 1.0F
            If score1 = 0.0F AndAlso score2 = 0.0F Then Return 0.0F
            ' Return weighted result
            Return (score1 * 0.2F) + (score2 * 0.8F)
        End Function
    
        Private Shared Function InternalGetSimilarityScore(s1 As String, s2 As String) As SqlDouble
            Dim dist As SqlInt32 = ComputeLevenstheinDistance(s1, s2)
            Dim maxLen As Integer = If(s1.Length > s2.Length, s1.Length, s2.Length)
            If maxLen = 0 Then Return 1.0F
            Return 1.0F - Convert.ToDouble(dist.Value) / Convert.ToDouble(maxLen)
        End Function
    
        ''' <summary>
        ''' Removes all non-alpha numeric characters and then sorts
        ''' the words in alphabetical order.
        ''' </summary>
        Private Shared Function GetSimilarityString(s1 As String) As String
            Dim normString = Regex.Replace(If(s1, ""), "\W|_", " ", Xms)
            normString = Regex.Replace(normString, "\s+", " ", Xms).Trim()
            Dim words As New List(Of String)(normString.Split(" "c))
            words.Sort()
            Return String.Join(" ", words.ToArray())
        End Function
    
    End Class
    
  3. ==============================

    3.

    select id, title
    from my_table
    where 
        title like 'Aliens%' 
        and 
        len(rtrim(title)) < len('Aliens') + 7
    
  4. ==============================

    4.내가 부탁 한 일에서 원래의 제목의 끝에 하나의 단어 이하이어야한다 찾고있는 차이를 상상한다. 이유는 1, 2, 4가 반환되는가요?

    내가 부탁 한 일에서 원래의 제목의 끝에 하나의 단어 이하이어야한다 찾고있는 차이를 상상한다. 이유는 1, 2, 4가 반환되는가요?

    어쨌든 나는 공백없이 말 검사의 차이가 하나의 단어로 구성하는 질의를했습니다.

    declare @title varchar(20)
    set @title = 'Aliens'
    select id, title
    from movies with (nolock)
    where ltrim(title) like @title + '%'
    and Charindex(' ', ltrim(right(title, len(title) - len(@title)))) = 0
    and len(ltrim(right(title, len(title) - len(@title)))) < 7
    

    그것이 도움이되기를 바랍니다.

  5. ==============================

    5.SQL Server 2008을 사용하는 경우는 전체 텍스트 기능을 사용할 수 있어야합니다.

    SQL Server 2008을 사용하는 경우는 전체 텍스트 기능을 사용할 수 있어야합니다.

    기본 단계는 다음과 같습니다

    1) 컬럼을 통해 전체 텍스트 인덱스를 만듭니다. 이것은 각각의 문자열 (깃발, 스플리터 등) 토큰 화하고 'LIKE THIS'문자열을 검색 할 수 있습니다.

    부인은 내가 그것을 사용했던 적이하지만 난 당신이 원하는 것을 할 수 있다고 생각한다는 것입니다.

    여기에 읽기 시작 : http://msdn.microsoft.com/en-us/library/ms142571.aspx

  6. from https://stackoverflow.com/questions/5299996/find-sql-records-containing-similar-strings by cc-by-sa and MIT license