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

SQL:在字符串中查找连续的重复字符,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在尝试使用SQL server在列中查找4个或更多连续的重复字符。在此方面的任何帮助都将不胜感激 我的数据: CompanyName HSBC Inc Barcccclays AAAAA Testtttt Tesco Plc 我的输出应如下所示: CompanyName Barcccclays AAAAA Testtttt 提前谢谢 我想说,最简单的解决方案是根据需要启用并实施您的条件。在这里,您可以使用正则表达式的强大功能,例如:类 您需要的正则表达式应与.\1{3}行一致,该行与后跟

我正在尝试使用SQL server在列中查找4个或更多连续的重复字符。在此方面的任何帮助都将不胜感激

我的数据:

CompanyName
HSBC Inc
Barcccclays
AAAAA
Testtttt
Tesco Plc
我的输出应如下所示:

CompanyName
Barcccclays
AAAAA
Testtttt

提前谢谢

我想说,最简单的解决方案是根据需要启用并实施您的条件。在这里,您可以使用正则表达式的强大功能,例如:类

您需要的正则表达式应与.\1{3}行一致,该行与后跟同一字符的任何字符至少匹配3次

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

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


在纯TSQL中实现相同的条件是完全可能的,只是读取和维护起来可能会很混乱。例如,考虑一下蛮力的解决方案,想想将来需要改变的条件会怎样,哪怕只是稍微复杂一点。

< P>是的,这是可能的,但是我不会在没有ReGEX函数的SQLServer中执行它:

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)
工作原理:

1生成复制值,如“aaaa”、“bbbb”、“cccc”等

2检查您的字符串是否包含它

警告

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

编辑:

如何合并上述代码:从tabc中选择@flag=1,其中1=使用mul作为select REPLICATECHAR32+N,从select top 95行中选择4作为val,从master中以t1.number作为N排序。从LENCompanyName>4的tabc中选择t1作为s select*,从CHARINDEXmul.val,c.CompanyName>0的mul中选择1

我得到了这个错误:如果这个语句是一个公共表表达式,或者是一个更改跟踪上下文子句,那么前面的语句必须以分号终止。请帮忙

如果您需要在无法使用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)
如果你有一份handy,这是小菜一碟。下面的两个解决方案都很简单,不需要CLR集成,并且在性能方面将关闭任何regex替代方案的大门

-- 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;
结果


不幸的是,文本处理并不是t-SQL的一个特别强大的部分。这必须在DB中完成吗?是的,这是管理规则之一的一部分。对于这样的事情,可能重复CLR是完全多余的。一个好的Ngrams函数或数字表,以及对REPLICATE和CHARINDEX的基本理解,才是真正需要的。@AlanBurstein,如果需求从未改变,那可能是太过分了。但我要说的是,SQLCLR是一个未被充分利用的特性,对于其他类似的问题,应该进行一些升级。若您追求的是可维护性的生产力,那个么我仍然更喜欢测试调试更改SQLCLR而不是TSQL。YMMV.Hi,如何合并上述代码:从tabc中选择@flag=1,其中1=使用mul作为select REPLICATECHAR32+N,4 AS val FROM select top 95 row_number overorder by t1.number AS N FROM master..spt_值t1 AS s select*从LENCompanyName>4的选项卡c中选择,存在从CHARINDEXmul.val,c.CompanyName>0的mul中选择1。我得到了这个错误:如果这个语句是一个公共表表达式,或者是一个更改跟踪上下文子句,那么前面的语句必须以分号终止。请帮忙。非常感谢!非常感谢。当我将EXISTS更改为NOT-EXISTS时,它给了我一个错误:“子查询返回的值超过1。”。当子查询在=、!=、=或者当子查询用作表达式时。“。我怎样才能纠正这个问题?蒂亚@user7617078我建议您使用完整的查询和示例数据提出新问题。抱歉,下面是代码:从选项卡c中选择*其中LENCompanyName>4且不存在从SELECT REPLICATECHAR32+N中选择1,4作为val从选择前95行中按t1排序。数字作为N从主..spt作为s mul值t1,其中CHARINDEXmul.val,c.CompanyName>0
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)
-- 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