我试图使用SQL服务器在列中找到4个或更多连续的重复字符。对此有任何帮助将非常感激。
我的数据:
CompanyName
HSBC Inc
Barcccclays
AAAAA
Testtttt
Tesco Plc
我的输出应该如下:
CompanyName
Barcccclays
AAAAA
Testtttt
提前致谢!
答案 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