2017-08-02 131 views
1

我试图在使用SQL Server的列中查找4个或更多个连续的重复字符。任何帮助,将不胜感激。SQL:在字符串中查找连续的重复字符

我的数据:

CompanyName 
HSBC Inc 
Barcccclays 
AAAAA 
Testtttt 
Tesco Plc 

我的输出应该如下:

CompanyName 
Barcccclays 
AAAAA 
Testtttt 

提前感谢!

+4

不幸的是,文字处理不是T-SQL的特别强的部分。这是否必须在数据库中完成? –

+0

是的,这是管理职责的一部分。 – user7617078

+2

[查找内部带有重复字母的字符串]可能的副本(https://stackoverflow.com/questions/14574990/finding-strings-with-duplicate-letters-inside) – JeffUK

回答

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)检查你的字符串是否包含它。

警告!只有

该解决方案检查ASCII字符从32到126

编辑:

How can incorporate above code like this: select @flag = 1 from tabc where 1 = (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)).

I'm getting this error:If this statement is a common table expression, or a change tracking context clause, the previous statement must be terminated with a semicolon. pls help

如果你需要使用它在上下文中,你不能用它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) 
+0

嗨,怎么能这样纳入上面的代码: – user7617078

+0

嗨,这样可以如何结合上面的代码:select tab = 1 from tabc其中1 =(WITH mul AS ( )SELECT REPLICATE(CHAR(32 + N),4 )AS VAL FROM(选择顶部95 ROW_NUMBER()在如N 从master..spt_values T1(由t1.number顺序))为S ) SELECT * FROM TABCç WHERE LEN(公司名称)> 4 AND EXISTS(SELECT 1 FROM mul WHERE CHARINDEX(mul.val,c.CompanyName)> 0))。我得到这个错误:如果这个语句是一个公用表表达式或者一个变更跟踪上下文子句,那么前面的语句必须以分号结尾。请帮助。 – user7617078

+1

非常感谢!非常感激。 – user7617078

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中的蛮力解决方案,并考虑在未来需要更改所需条件时会发生什么,甚至会更复杂一点。

+0

'在纯TSQL中实现相同的条件完全可行只是它可能是一个乱七八糟的阅读,因为它总是取决于:) – lad2025

+0

一个CLR是完全矫枉过正这样的事情。一个好的Ngrams函数或Numbers表,以及REPLICATE和CHARINDEX的基本理解实际上都是必需的。 –

+0

@AlanBurstein,如果需求永远不会改变 - 也许是矫枉过正。但是我会说SQLCLR是一个未被充分利用的功能,并且对于其他类似问题的一点促销也是有用的。如果您是在维护性的生产力之后,那么我仍然更希望通过TSQL更改测试调试SQLCLR。因人而异。 –

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 
相关问题