Solución:
Si realmente desea definir la similitud de la manera exacta en que lo formuló en su pregunta, entonces, como dice, tendría que implementar el cálculo de la distancia de Levensthein. Ya sea en el código calculado en cada fila recuperada por un DataReader o como una función de SQL Server.
El problema planteado es en realidad más complicado de lo que puede parecer a primera vista, porque no se puede asumir que se sabe cuál es el problema. mutuamente compartido los elementos entre dos cadenas pueden ser.
Entonces, además de la Distancia de Levensthein, probablemente también desee especificar un número mínimo de caracteres consecutivos que realmente deben coincidir (para que se concluya la similitud suficiente).
En resumen: suena como un enfoque demasiado complicado y lento / lento.
Curiosamente, en SQL Server 2008 tiene la función DIFFERENCE que mayo ser utilizado para algo como esto.
Evalúa el valor fonético de dos cadenas y calcula la diferencia. No estoy seguro de si logrará que funcione correctamente para expresiones de varias palabras, como títulos de películas, ya que no maneja bien los espacios o números y pone demasiado énfasis en el comienzo de la cadena, pero sigue siendo interesante. predicado a tener en cuenta.
Si lo que eres Realmente tratar de describir es una especie de función de búsqueda, entonces debería buscar en las capacidades de búsqueda de texto completo de SQL Server 2008. Proporciona soporte de tesauro integrado, predicados SQL sofisticados y un mecanismo de clasificación para las “mejores coincidencias”
EDITAR: Si está buscando eliminar duplicados, tal vez pueda buscar SSIS Fuzzy Lookup y Fuzzy Group Transformation. No lo he probado yo mismo, pero parece una pista prometedora.
EDIT2: Si no desea profundizar en SSIS y aún tiene dificultades con el rendimiento del algoritmo de distancia de Levensthein, tal vez podría probar este algoritmo que parece ser menos complejo.
Para todos los empleados de Google que se encuentran con esta pregunta, aunque ya se marcó como respondida, pensé que compartiría un código para ayudar con esto. Si puede realizar funciones CLR definidas por el usuario en su servidor SQL, puede implementar su propio algoritmo de distancia de Levensthein y, a partir de ahí, crear una función que le proporcione una ‘puntuación de similitud’ llamada dbo.GetSimilarityScore()
. He basado mi puntuación en la no distinción entre mayúsculas y minúsculas, sin mucho peso, en el orden de las palabras mezcladas y los caracteres no alfanuméricos. Puede ajustar su algoritmo de puntuación según sea necesario, pero este es un buen comienzo. Crédito a este enlace del proyecto de código por comenzar.
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
select id, title
from my_table
where
title like 'Aliens%'
and
len(rtrim(title)) < len('Aliens') + 7