AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 13593
Accepted
db2
db2
Asked: 2012-02-22 10:06:06 +0800 CST2012-02-22 10:06:06 +0800 CST 2012-02-22 10:06:06 +0800 CST

Pesquisa difusa sob demanda

  • 772

Temos uma tabela de clientes (quem não tem?), contendo muitos registros que são, do ponto de vista comercial, duplicados. Consegui criar um pacote SSIS para executar o agrupamento difuso e relatar possíveis duplicatas.

Agora, suponha que eu queira fazer esse tipo de análise no momento em que alguém está entrando em um novo cliente. A ideia seria realizar uma pesquisa difusa no nome do cliente (e possivelmente alguma outra informação básica, como código postal) e mostrar possíveis duplicatas antes de prosseguir para o formulário de criação do cliente.

O problema óbvio aqui é que o agrupamento difuso e os componentes de pesquisa fazem parte do SSIS. Se eu quisesse executá-los sob demanda, teria que fazer algo insano como colocar os termos de pesquisa em uma tabela de preparação, executar o pacote SSIS, aguardar sua conclusão e buscar os resultados de uma tabela de saída. Seria lento, doloroso e teria graves problemas de simultaneidade.

Então, a outra ideia era usar a indexação de texto completo. Ao experimentá-lo, parece que não será adequado. Ele não detecta erros ortográficos sutis de nomes de clientes ou nomes que diferem em "Empresa" x "Corporação" x "Sociedade", ou "Anderson" x "Andersen" e outras variações desse tipo.

Existe algo que permitirá a flexibilidade do agrupamento/correspondência difusa do T-SQL? Posso dizer a uma pesquisa difusa para salvar os tokens, mas parece que ainda teria que reimplementar a maior parte do algoritmo de correspondência para usá-los.

sql-server sql-server-2008
  • 1 1 respostas
  • 6226 Views

1 respostas

  • Voted
  1. Best Answer
    Rachel
    2012-02-22T12:30:48+08:002012-02-22T12:30:48+08:00

    No passado, construí uma "pesquisa difusa" em uma função .Net CLR. Essa função é chamada da mesma forma que uma função definida pelo usuário é chamada.

    Por exemplo,

    select id, name
    from customers
    where dbo.CompareStrings("newCustomerName", customers.name) > .8
    

    retornaria apenas clientes com um nome 80% semelhante ao nome de entrada.

    A % de correspondência é baseada no número de alterações necessárias para converter um valor em outro, não no número de caracteres diferentes. Nós o usamos para comparar endereços e descobrimos que isso é mais eficaz devido às inúmeras abreviações de ruas usadas.

    Aqui está o código que usei para comparar strings. Eu fiz isso há tanto tempo que não consigo lembrar como implantá-lo, embora uma pesquisa rápida mostre muitos artigos sobre como criar funções SQL CLR

    ' Checks two strings against each other and returns a decimal between 0 (doesn't match at all) and 1 (100% match)
    <Microsoft.SqlServer.Server.SqlFunction()> _
    Public Shared Function CompareStrings(ByVal input1 As SqlChars, ByVal input2 As SqlChars) _
    As <SqlFacet(Precision:=10, Scale:=4)> SqlDecimal
    
        If IsNothing(input1) And IsNothing(input2) Then
            Return New SqlDecimal(1.0)
        ElseIf IsNothing(input1) Or IsNothing(input2) Then
            Return New SqlDecimal(0.0)
        End If
    
        Dim s1 As String = New String(input1.Value)
        Dim s2 As String = New String(input2.Value)
    
        If s1.Length = 0 Or s2.Length = 0 Then
            Return New SqlDecimal(1.0)
        Else
            Dim re As New Regex("[^A-Za-z0-9 ]", RegexOptions.IgnorePatternWhitespace Xor RegexOptions.Singleline)
            s1 = re.Replace(s1, "( )\1*", "$1")
            s2 = re.Replace(s2, "( )\1*", "$1")
            s1 = UCase(re.Replace(s1, ""))
            s2 = UCase(re.Replace(s2.ToString, ""))
    
            Dim dif As Integer = GetStringSimilarity(s1, s2)
            Dim max As Integer = s1.Length
            If s2.Length > max Then max = s2.Length
    
            Return New SqlDecimal(1.0 - (dif / max))
        End If
    End Function
    
    ' Compares two strings using the relationship in patterns of letters
    Private Shared Function GetStringSimilarity(ByVal s1 As String, ByVal s2 As String) As Integer
        Dim n As Integer = s1.Length
        Dim m As Integer = s2.Length
        Dim distance(n + 1, m + 1) As Integer
    
        Dim cost As Integer = 0
        If n = 0 Then Return m
        If m = 0 Then Return n
    
        For i As Integer = 0 To n
            distance(i, 0) = i
        Next
        For j As Integer = 0 To m
            distance(0, j) = j
        Next
    
        For i As Integer = 1 To n
            For j As Integer = 1 To m
                If Mid(s2, j, 1) = Mid(s1, i, 1) Then cost = 0 Else cost = 1
                distance(i, j) = Min3(distance(i - 1, j) + 1, distance(i, j - 1) + 1, distance(i - 1, j - 1) + cost)
            Next
        Next
        Return distance(n, m)
    End Function
    
    ' Returns the min of 3 values
    Private Shared Function Min3(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer) As Integer
        Dim min As Integer = x
        If y < min Then min = y
        If z < min Then min = z
        Return min
    End Function
    
    • 2

relate perguntas

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Quanto "Padding" coloco em meus índices?

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

  • Como determinar se um Índice é necessário ou necessário

  • Downgrade do SQL Server 2008 para 2005

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Como selecionar a primeira linha de cada grupo?

    • 6 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve