【问题标题】:SQL Get Rows With A Similar Column ValueSQL 获取具有相似列值的行
【发布时间】:2014-02-06 08:35:43
【问题描述】:

我有一个数据库,有时会存储重复的行,但是重复的行并不明确,例如以下两列值将重复:

G12345 & G1234 --> because they are very similar 
(a string comparison shows that the characters match 83.3%).

我需要一些帮助来编写一个SQL 查询,该查询将检索与作为查询的一部分发送的字符串非常相似的值,例如超过 50% 的字符匹配。

有人可以帮忙吗?我有一个 C# 方法如下,但不太确定如何在 SQL 中完成此操作:

static double StringCompare(string a, string b)
{
  if (a == b) //Same string, no iteration needed.
    return 100;
  if ((a.Length == 0) || (b.Length == 0)) //One is empty, second is not
  {
    return 0;
  }
  var maxLen = a.Length > b.Length ? a.Length : b.Length;
  var minLen = a.Length < b.Length ? a.Length : b.Length;
  var sameCharAtIndex = 0;
  for (var i = 0; i < minLen; i++) //Compare char by char
  {
    if (a[i] == b[i])
    {
      sameCharAtIndex++;
    }
  }
  return sameCharAtIndex / maxLen * 100;
}

提前致谢。

【问题讨论】:

    标签: asp.net sql sql-server


    【解决方案1】:

    不确定您尝试使用 SQL-Server 还是 MySQL,但您可以在 SQL-Server 中创建和使用以下函数:

    create function StringCompare
        (@A nvarchar(200),
        @B nvarchar(200)
        )
    returns float
    as
    begin
        if (
            @A = @B
            or (@A is null and @B is null)
            )
        begin
            return 100.0
        end
    
        if (
            ((@A is null or len(@A) = 0) and (@B is not null and len(@B) > 0))
            or ((@B is null or len(@B) = 0) and (@A is not null and len(@A) > 0))
            )
        begin
            return 0.0
        end
    
        declare @maxLen int
        set @maxLen = case when len(@A) > len(@B) then len(@A) else len(@B) end
    
        declare @minLen int
        set @minLen = case when len(@A) < len(@B) then len(@A) else len(@B) end
    
        declare @sameCharAtIndex int
        set @sameCharAtIndex = 0
    
        declare @count int
        set @count = 1
    
        while (@count <= @minLen)
        begin
            if (SUBSTRING(@A, @count, 1) = substring(@B, @count, 1))
            begin
                set @sameCharAtIndex = @sameCharAtIndex + 1
            end
    
            set @count = @count + 1
        end
    
        return cast(@sameCharAtIndex as float) / cast(@maxLen as float) * 100.0
    
    end
    

    可以在如下任何语句中使用:

    select dbo.StringCompare('test', 'test'), dbo.StringCompare('nope', 'test'),  dbo.StringCompare('partial', 'parsomethingelse')
    

    请注意,在许多记录上运行的 sql 中使用这样的循环可能效率低下。而且你可能要考虑是否真的必须在sql中进行。

    【讨论】:

    • 感谢这个非常有用的东西,我会试试看。搜索将仅限于几条记录。
    【解决方案2】:

    使用Mysql Like Operator,而不是在服务层做。

    SELECT * FROM table WHERE column LIKE 'G12___' or 'G12%'.
    
    SELECT * FROM table WHERE column LIKE '%input string as parameter%'.
    

    LIKE 谓词中的“_”通配符表示“任意字符之一”,相当于“.”。在正则表达式中。

    参考this

    【讨论】:

    • 来吧,这个规模如何。 G12345 只是一个例子
    • 是的,这是正确的,提供的数据只是一个例子,我正在寻找可以正确缩放并且字符可能不连续的东西。
    • @user2310289 :仅供参考,您可以将其作为 sql 中的参数传递。这就是它的扩展方式。
    猜你喜欢
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    相关资源
    最近更新 更多