SQL:在字符串中查找连续的重复字符

时间:2017-08-02 10:01:35

标签: sql sql-server tsql

我试图使用SQL服务器在列中找到4个或更多连续的重复字符。对此有任何帮助将非常感激。

我的数据:

CompanyName
HSBC Inc
Barcccclays
AAAAA
Testtttt
Tesco Plc

我的输出应该如下:

CompanyName
Barcccclays
AAAAA
Testtttt

提前致谢!

3 个答案:

答案 0 :(得分:3)

是的,这是可能的,但如果没有正则表达式功能,我不会在SQL Server中执行此操作:

CREATE TABLE tabC(CompanyName VARCHAR(100));

INSERT INTO tabC(CompanyName) 
    SELECT 'HSBC Inc' UNION ALL
    SELECT 'Barcccclays' UNION ALL
    SELECT 'AAAAA' UNION ALL
    SELECT 'Testtttt' UNION ALL
    SELECT 'Tesco Plc';

WITH mul AS
(
   SELECT REPLICATE(CHAR(32 + N), 4) AS val
   FROM (select top 95 row_number() over(order by t1.number) as N
         from   master..spt_values t1)  AS s
)
SELECT *
FROM tabC c
WHERE LEN(CompanyName) > 4
  AND EXISTS (SELECT 1
              FROM mul
              WHERE CHARINDEX(mul.val,c.CompanyName) > 0)

<强> RextesterDemo

工作原理:

1)生成'aaaa','bbbb','cccc'等复制值

2)检查你的字符串是否包含它。

警告!

此解决方案仅检查32到126之间的ASCII字符。

修改

  

如何合并上面这样的代码:从tabc中选择@flag = 1,其中1 =(WITH mul AS(SELECT REPLICATE(CHAR(32 + N),4)AS val FROM(select top 95 row_number()over(由t1.number命令)作为N来自master..spt_values t1)AS s)SELECT * FROM tabC c WHERE LEN(CompanyName)&gt; 4 AND EXISTS(SELECT 1 FROM mul WHERE CHARINDEX(mul.val,c.CompanyName)&gt ; 0))。

     

我收到此错误:如果此语句是公用表表达式或更改跟踪上下文子句,则必须以分号结束前一个语句。请帮助

如果您需要在无法使用CTE的情况下使用它,请将其更改为子查询。

SELECT *
FROM tabC c
WHERE LEN(CompanyName) > 4
  AND EXISTS (SELECT 1
              FROM (SELECT REPLICATE(CHAR(32 + N), 4) AS val
                    FROM (select top 95 row_number() over(order by t1.number) as N
                          from master..spt_values t1)  AS s) mul
              WHERE CHARINDEX(mul.val,c.CompanyName) > 0)

答案 1 :(得分:2)

我想说最简单的解决方案是启用SQL CLR并将您的条件设为user-defined function in .NET。在那里你可以使用正则表达式的强大功能(例如:Regex类)。

你需要的正则表达式是(.)\1{3}的行,它匹配任何字符,后面跟着同一个字符至少3次。

例如,UDF可以用C#编写,如下所示:

using Microsoft.SqlServer.Server;
using System;
using System.Data.SqlTypes;
using System.Text.RegularExpressions;

public partial class UserDefinedFunctions
{
    [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
    public static SqlBoolean ContainsRepeatingCharacters(SqlString input)
    {
        const String pattern = @"(.)\1{3}";     
        Boolean hasMatch = Regex.IsMatch(input.ToString(), pattern);
        return new SqlBoolean(hasMatch);
    }
}

然后您可以像使用任何其他UDF一样使用它:

select companyName
from companies
where dbo.ContainsRepeatingCharacters(companyName) = 1

在纯TSQL中实现相同的条件是可能的,只是它可能是一个乱七八糟的读取和维护。例如,考虑this post中的蛮力解决方案,并考虑在将来改变所需条件时会发生什么,即使只是更复杂一些。

答案 2 :(得分:0)

如果您有NGrams8K的副本,这是一块蛋糕。下面的两个解决方案都很简单,不需要CLR集成,并且会在性能方面打破任何正则表达式的替代方案。

-- sample data
DECLARE @table table 
(
  CompanyName varchar(100) 
  unique /* included to simulate an index on this column */
);
INSERT @table values('HSBC Inc'),('Barcccclays'),('AAAAA'),('Testtttt'),('Tesco Plc');

-- solution #1
SELECT companyname
FROM @table
CROSS APPLY dbo.ngrams8K(CompanyName,1)
WHERE charindex(replicate(token,4), CompanyName) > 0
GROUP BY CompanyName;

-- solution #2 (if you want to return a boolean)
SELECT companyname, has4ConsecChars = max(sign(charindex(replicate(token,4), CompanyName)))
FROM @table
CROSS APPLY dbo.ngrams8K(CompanyName,1)
GROUP BY CompanyName;

<强>结果

companyname
---------------
AAAAA
Barcccclays
Testtttt   

companyname     has4ConsecChars
--------------- ---------------
AAAAA           1
Barcccclays     1
HSBC Inc        0
Tesco Plc       0
Testtttt        1