Sql server sql中的逐字符比较字符串

Sql server sql中的逐字符比较字符串,sql-server,string,tsql,Sql Server,String,Tsql,如何比较字符上的字符串,使用T-SQL检查字符串是否由相同的符号组成 例如: “aaabbcd”vs“ddbca”TRUE:两个字符串由相同的符号组成 “abcddd”与“cda”错误:两个字符串不包含相同的符号 可以使用此“%your search string%”查找包含任何子字符串的字符串 SELECT * FROM TableName WHERE Name LIKE '%searchText%' 可以使用存储过程检查字符串中的字符 CREATE PROCEDURE IsStringMa

如何比较字符上的字符串,使用T-SQL检查字符串是否由相同的符号组成

例如:

“aaabbcd”vs“ddbca”TRUE:两个字符串由相同的符号组成 “abcddd”与“cda”错误:两个字符串不包含相同的符号 可以使用此“%your search string%”查找包含任何子字符串的字符串

SELECT * FROM TableName
WHERE Name LIKE '%searchText%'
可以使用存储过程检查字符串中的字符

CREATE PROCEDURE IsStringMatching
(
@originalString NVARCHAR(32) ,
@stringToBeChecked NVARCHAR(32),
@IsMatching BIT OUTPUT
)
AS
BEGIN
     DECLARE @inputStringCount INT = LEN(@originalString);
     DECLARE @loopCount INT = 0, @temp INT; 
     DECLARE @char VARCHAR;
     SET @IsMatching = 1
     WHILE @loopCount < @inputStringCount
        BEGIN
            SET @char = SUBSTRING(@originalString,@loopCount+1,1);
             SET @temp =  CHARINDEX(@char, @stringToBeChecked,1);
             IF(@temp = 0)
                BEGIN
                    SET @IsMatching = 0;
                    BREAK;
                END             
            SET @loopCount = @loopCount + 1;
        END;    
END
可以使用此“%your search string%”查找包含任何子字符串的字符串

SELECT * FROM TableName
WHERE Name LIKE '%searchText%'
可以使用存储过程检查字符串中的字符

CREATE PROCEDURE IsStringMatching
(
@originalString NVARCHAR(32) ,
@stringToBeChecked NVARCHAR(32),
@IsMatching BIT OUTPUT
)
AS
BEGIN
     DECLARE @inputStringCount INT = LEN(@originalString);
     DECLARE @loopCount INT = 0, @temp INT; 
     DECLARE @char VARCHAR;
     SET @IsMatching = 1
     WHILE @loopCount < @inputStringCount
        BEGIN
            SET @char = SUBSTRING(@originalString,@loopCount+1,1);
             SET @temp =  CHARINDEX(@char, @stringToBeChecked,1);
             IF(@temp = 0)
                BEGIN
                    SET @IsMatching = 0;
                    BREAK;
                END             
            SET @loopCount = @loopCount + 1;
        END;    
END
内联方法

这使用了一个数字表

CREATE TABLE dbo.Numbers (number INT PRIMARY KEY);

INSERT INTO dbo.Numbers
SELECT TOP 8000 ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM sys.all_columns c1, 
     sys.all_columns c2
如果您希望在性能与不使用性能之间进行权衡,则编辑历史记录中将显示一个没有性能但性能较差的版本

WITH T(S1, S2) 
     AS (SELECT 'aaabbcd', 
                'ddbca' 
         UNION ALL 
         SELECT 'abcddd', 
                'cda')
SELECT * 
FROM   T 
       CROSS APPLY (SELECT CASE WHEN Min(Cnt) = 2 THEN 1 ELSE 0 END AS Flag 
                    FROM   (SELECT Count(*) AS Cnt 
                            FROM   (SELECT 1                           AS s, 
                                           Substring(S1, N1.number, 1) AS c 
                                    FROM   dbo.Numbers N1 
                                    WHERE  N1.number <= Len(S1) 
                                    UNION 
                                    SELECT 2                           AS s, 
                                           Substring(S2, N2.number, 1) AS c 
                                    FROM   dbo.Numbers N2 
                                    WHERE  N2.number <= Len(S2)) D1 
                            GROUP  BY c) D2 
                    ) Ca 
内联方法

这使用了一个数字表

CREATE TABLE dbo.Numbers (number INT PRIMARY KEY);

INSERT INTO dbo.Numbers
SELECT TOP 8000 ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM sys.all_columns c1, 
     sys.all_columns c2
如果您希望在性能与不使用性能之间进行权衡,则编辑历史记录中将显示一个没有性能但性能较差的版本

WITH T(S1, S2) 
     AS (SELECT 'aaabbcd', 
                'ddbca' 
         UNION ALL 
         SELECT 'abcddd', 
                'cda')
SELECT * 
FROM   T 
       CROSS APPLY (SELECT CASE WHEN Min(Cnt) = 2 THEN 1 ELSE 0 END AS Flag 
                    FROM   (SELECT Count(*) AS Cnt 
                            FROM   (SELECT 1                           AS s, 
                                           Substring(S1, N1.number, 1) AS c 
                                    FROM   dbo.Numbers N1 
                                    WHERE  N1.number <= Len(S1) 
                                    UNION 
                                    SELECT 2                           AS s, 
                                           Substring(S2, N2.number, 1) AS c 
                                    FROM   dbo.Numbers N2 
                                    WHERE  N2.number <= Len(S2)) D1 
                            GROUP  BY c) D2 
                    ) Ca 

如果性能很重要,那么我建议使用一个纯基于集合的解决方案

这将为您提供正确答案:

SELECT AllSame = COALESCE(MAX(0),1)
FROM dbo.ngrams8k(@string1, 1) ng1
FULL JOIN dbo.ngrams8k(@string2, 1) ng2 ON ng1.token = ng2.token
WHERE ng1.token IS NULL OR ng2.token IS NULL;
要对表使用此逻辑,可以使用如下交叉应用:

-- Sample data
DECLARE @table TABLE (string1 varchar(100), string2 varchar(100));
INSERT @table VALUES ('aaabbcd','ddbca'),('abcddd','cda');

-- Solution using CROSS APPLY
SELECT * 
FROM @table t
CROSS APPLY
(
  SELECT AllSame = COALESCE(MAX(0),1)
  FROM dbo.ngrams8k(t.string1, 1) ng1
  FULL JOIN dbo.ngrams8k(t.string2, 1) ng2 ON ng1.token = ng2.token
  WHERE ng1.token IS NULL OR ng2.token IS NULL
) x;
结果:

string1   string2   AllSame
--------- --------- --------
aaabbcd   ddbca     1
abcddd    cda       0
这不仅是迄今为止提出的最快的解决方案,还要注意,我们用尽可能少的代码完成了这项工作

更新内容包括将性能与MARTIN SMITH的解决方案进行比较


请注意,我没有使用并行计划测试Martin的解决方案,因为该查询不能并行运行

如果性能很重要,那么我建议使用一种纯粹基于集合的解决方案

这将为您提供正确答案:

SELECT AllSame = COALESCE(MAX(0),1)
FROM dbo.ngrams8k(@string1, 1) ng1
FULL JOIN dbo.ngrams8k(@string2, 1) ng2 ON ng1.token = ng2.token
WHERE ng1.token IS NULL OR ng2.token IS NULL;
要对表使用此逻辑,可以使用如下交叉应用:

-- Sample data
DECLARE @table TABLE (string1 varchar(100), string2 varchar(100));
INSERT @table VALUES ('aaabbcd','ddbca'),('abcddd','cda');

-- Solution using CROSS APPLY
SELECT * 
FROM @table t
CROSS APPLY
(
  SELECT AllSame = COALESCE(MAX(0),1)
  FROM dbo.ngrams8k(t.string1, 1) ng1
  FULL JOIN dbo.ngrams8k(t.string2, 1) ng2 ON ng1.token = ng2.token
  WHERE ng1.token IS NULL OR ng2.token IS NULL
) x;
结果:

string1   string2   AllSame
--------- --------- --------
aaabbcd   ddbca     1
abcddd    cda       0
这不仅是迄今为止提出的最快的解决方案,还要注意,我们用尽可能少的代码完成了这项工作

更新内容包括将性能与MARTIN SMITH的解决方案进行比较


请注意,我没有使用并行计划测试Martin的解决方案,因为该查询不能并行运行

OP想知道两个字符串中是否使用了相同的字符集,而不管顺序如何。如果我们检查字符集是否相同,那么示例中的真实情况如何发生。不过有点混乱。两个字符串中的字母A、b、c和d都是真的。a、 b c和d在一个字符串中,但在另一个字符串中只有a、c和d-FALSE。在这个问题上,此函数似乎可以验证第二个字符串是否包含与第一个字符串相同的所有字符。如果OP指示无论计数多少,两个字符串都必须具有完全相同的字符,那么很遗憾,这不会起作用。您可以通过abcd和abcdXYZ进行测试,结果是@IsMatching=1。OP想知道两个字符串中是否使用了相同的字符集,而不管顺序如何。如果我们检查字符集是否相同,示例中的真实情况如何发生。不过有点混乱。两个字符串中的字母A、b、c和d都是真的。a、 b c和d在一个字符串中,但在另一个字符串中只有a、c和d-FALSE。在这个问题上,此函数似乎可以验证第二个字符串是否包含与第一个字符串相同的所有字符。如果OP指示无论计数多少,两个字符串都必须具有完全相同的字符,那么很遗憾,这不会起作用。您可以通过abcd和abcdXYZ进行测试,结果是@IsMatching=1。而不是通过@spid进行过度排序通过选择NULL进行过度排序,这将防止不必要的排序。@AlanBurstein Sql server意识到@spid是一个常量。这是一件奇怪的事情,但当您对虚拟数据使用sys.all_列时,由于某种原因,优化器更倾向于按SELECT NULL排序,而不是按@SPID排序。比较这两种方法的执行计划:从sys.all\u列中选择ORDER BY@@SPID NUMBER上的前100行\u编号;通过从sys.all_列中选择空编号,选择订单上的前100行编号@AlanBurstein-syscolpars和sysobjvalues之间的连接类型?如果添加了一个显式的选项merge join提示,那么计划看起来是一样的,因此不确定是否有任何特殊原因导致它没有达到这个目的,或者在本例中只是一个怪癖。现在只看一下您的测试-我将添加一个带有永久数字表的版本到混合中,因为Nums的定义显然有一些无关的东西,这对性能没有帮助。与其按@过多排序,不如按@过多排序spid按选择NULL过多排序,这将防止不必要的排序。@AlanBurstein Sql server意识到这一点@@SPID是一个常数。这是一件奇怪的事情,但当您对虚拟数据使用sys.all_列时,由于某种原因,优化器更倾向于按SELECT NULL排序,而不是按@SPID排序。比较两者的执行计划:选择
订单上方的前100行\u编号@@SPID NUMBER FROM sys.all\u列;通过从sys.all_列中选择空编号,选择订单上的前100行编号@AlanBurstein-syscolpars和sysobjvalues之间的连接类型?如果添加了一个显式的选项merge join提示,那么计划看起来是一样的,因此不确定是否有任何特殊原因导致它没有达到这个目的,或者在本例中只是一个怪癖。现在看一下您的测试——我将在混合中添加一个带有永久数字表的版本,因为NUM的定义显然有一些无关的东西,对性能没有帮助。最快解决方案声明需要一些测试结果。不过,如果你决定这样做,也可以在我的表中使用索引数字表。@MartinSmith-我准备了一个性能测试,并将它添加到我的原始帖子中供你审阅。干杯+1对于统计数据和测试装备-使用索引数字表,这些是我得到的统计数据。解决方案声明需要一些测试结果。不过,如果你决定这样做,也可以在我的表中使用索引数字表。@MartinSmith-我准备了一个性能测试,并将它添加到我的原始帖子中供你审阅。干杯+1对于统计数据和测试装备-使用索引数字表,这些是我得到的统计数据