使用sql获取未知字符串的模式?

时间:2016-03-17 13:11:24

标签: sql regex database sql-server-2008

我有数千个未知字符串,他们可能是电子邮件,phonenum

但他们不适合我意味着他们不是电子邮件或手机号码对我来说他们只是我的字符串,但我想要他们的共同模式所以这里是字符串为例子

链接到示例click here

现在我想要的是这个文件输出如果模式在这里3次,我正在做的是

 DECLARE @strs2 nvarchar(255)
 DECLARE @patternTable table(
id int ,



  order by p.pat 

但是我的例子返回了这个

       485-2889
       485-2889
       ) 485-2889
       ) 485-2889
       .aol.com/aol/search?
      .aol.com/aol/search?
        gmail.com 
     gmail.com 

但我想将此添加到模式

   [a-zA-Z 0-9] [a-zA-Z 0-9] [a-zA-Z 0-9] -  485-2889

用于gmail           [a-zA-Z 0-9] [a-zA-Z 0-9] @ gmail.com

1 个答案:

答案 0 :(得分:2)

首先,这比其看起来的更多更多的工作。 据我所知,它将成为繁重处理的方法(可能不是你想用SQL中的游标做的事情(游标在效率方面有点不好)。

必须为代码定义一种识别模式的方法。您还必须处理一组字符串与多个模式匹配的优先级。例如,如果您实现以下模式标准(在您的示例中):

BK-M18B-48
BK-M18B-52
BK-M82B-44
BK-M82S-38
BK-M82S-44
BK-R50B-58
BK-R50B-62
.....
should generate BK-[A-Z]-[0-9][0-9][A-Z]-[0-9][0-9]

然后下一组可以有多个模式:

fedexcarepackage@outlook.com (example added for explanations)
fedexcarepackage@office.com
fedexcourierexpress@pisem.net
fedexcouriers@gmail.com ( another example added for explanations)
.....

可以生成:

fedexc%@%.% (as you said)
fedexc%@%   (depending on processing)
fedexc[A-Z][A-Z]....%@%[A-Z]....[A-Z].[A-Z][A-Z][A-Z] (alphanumeris with '%' to compensate for length difference)

除此之外,如果您从字符串列表中删除fedexcarepackage@outlook.com,则会获得另外一种您可能不想拥有的模式:

fedexc%@%i%.%  (because they have 'i' somewhere between the '@' and '.' (dot)

无论如何,这是您必须考虑的设计。

我将为您提供一些可以使用的基本逻辑:

  1. 创建一个函数来识别每个不同的模式(1个模式/函数)。对于instnace,1个函数来检查字符串的静态片段(并附加通配符);另一个检测符合此模式条件的[A-Z],[0-9]模式是有效的;如果不同的模式需要更多。
  2. 创建一个函数来测试带有模式的字符串。所以说你有4个字符串,你在比较前两个字符时找到一个模式。然后使用函数测试模式是否适用于第3和第4个字符串。
  3. 创建一个函数来测试2个模式是否互斥。例如' PersonA @ yahoo。%'和' PersonA @%。net'如果它们都被测试为真,那么这些模式并不是相互排斥的。 ' Person%@yahoo.com'和' PersonB@yahoo.com'是相互排斥的(两种模式都不是真的,所以1是多余的。
  4. 创建一个函数来组合非互斥的模式(可能包括在第2和第3点使用函数)。所以' PersonA @ yahoo。%'和' PersonA @%。net'可以组合成人员@%。%'
  5. 完成设置后,循环浏览每个文本行,并根据每个模式条件将当前行与下一行进行比较。记录您找到的任何模式(在专用于该标准的变量中,(暂时不要混合它们)。 接下来是最困难的部分,最安全的方法是将每个模式与每个字符串进行比较,以排除那些不适用于所有字符串的模式。但是,你可能想出一种方法来组合模式(在同一类别中)而不进行交叉检查

    最后,在将每个模式类型的模式列表缩小为1个模式之后。将它们组合成1或消除那些

    请记住,在模式检测功能中,您可能需要多次测试每一行并组合模式。一些伪代码来演示:

    Function CompareForStringMatches (String s1, String s2){ -- it should return a possible pattern found.
       Array/List pattern;
       int patternsFound=0;
       For(i = 0, to length of shorter string){
          For(x = 0, to length of shorter string){
              if(longerString.contains(shorterString.substring(from i, to x)){
                 --record the pattern somewhere as:
                 pattern[patternsFound] = Replace(longerString, shorterString.Substring(from i, to x), '%') --pattern = longerString with substring replaced with '%' sign 
                 patternsFound = patternsFound+1;
              }
          }
       }
      --After loops make another loop to check (partial) patterns against each other to eliminate patterns that are part of a larger pattern
      --for instance Comparing 'random@asd.com' and 'sundom@asd.com' the patterns below should be found:
      ---compare'%andom@asd.com' and '%ndom@asd.com' and eliminate the first pattern, because both are valid, but second pattern includes the first one.
      --You will have a lot of similar matches, but if you do this, you should end up with only a few patterns.
      --after first cycle of checks do another one to combine patterns, where possible(for instance if you compare 'random@asd.com' and 'sundom@asd.net' you will end up with these 2 patterns'%ndom@asd.com' and 'Random@asd.%'.
      --Since these patterns are true (because they were found during a comparison) you can combine them into '%ndom@asd.%'
    
      --when you combine/eliminate all patterns, you should only have 1 left
      return pattern[only pattern left];
    }
    
    PS:你可以更有效地做事,但是如果你不知道从哪里开始,你可能需要做很长的工作并从第一个工作原型开始改进。

    修改/更新

    我建议您制作通配符检测方法,然后应用之前实施的其他模式检查。

    通配符检测,用于比较2个字符串(伪代码),重处理版本:

    比较2个字符串,检查较短字符串的每个可能段是否在更长的范围内:

    for(int i = 0; i<shorterString.Length;i++){
        for(int x = 0; i<shorterString.Length;i++){
            if(longerString.contains(shorterString.substring(i,x))){ --from i to x
                 possiblePattern.Add(longerString.replace(shorterString.substring(i,x),'*')
               --add to pattern list
            }
        }
    
        --Next compare partal matches and eliminate ones that are a part of larger pattern
        --So '*a@gmail.com' and '*na@yahoo.com' comparison should eliminate '*na@gmail.com', because if shorter pattern (with more symbols removed) is valid, then similar one with an extra symbol is part of it
    
    
        --When that is done, combine remaining matches if there's more than 1 left.
        --Remember, all patterns are valid if your first loop was correct, so '*@gmail.com' and 'personA@*.com' can be combined into '*@*.com
    
    }
    

    至于字母数字检测。我建议你先检查所有字符串的长度。如果它们相同,请运行通配符模式检测方法(对于所有这些)。完成后,只在通配符中查找patern匹配。

    因此,您将从通配符检测运行中获得类似BK-*-*的模式。在第二次迭代循环中,取2个字符串并仅提取由通配符表示的子字符串(使用数组或等效项来存储子字符串,确保不将单个字符串的通配符组合成1个字符串)。 因此,如果您与上面找到的模式(BK-*-*)进行比较:

    BK-M18B-48
    BK-M18B-52
    

    在消除静态字符后,您应该获取以下字符串集:

    Set 1:M18B and 48
    Set 2:M18B and 52
    

    将每个字符与相同位置的相反字符串进行比较,并检查字符是否与您的类别匹配(如String1 [0] .isaLetter AND St​​ring2 [0] .isaLetter)。如果他们确实将1个字符添加到模式中,如果不是:

    • 添加通配符(将导致模式如BK- [AZ] * [0-9] [0-9] - [0-9] [0-9]。如果这样做,请将相邻的通配符组合到1。
    • 模式是假的,你应该支持没有返回模式。

    使用此基本逻辑循环遍历字符串,为每组2个字符串创建(并存储!!!! )模式。循环通过模式,使用通配符检测(可能是较轻的版本)来组合/消除模式。所以,如果你得到像&#39; @ yahoo.com&#39;和&#39; @ gmail.com&#39;从不同的字符串集合中,您应该将它们组合成&#39; @ .com&#39;

    请注意很多的优化空间。