【问题标题】:Finding strings with duplicate letters inside查找内部有重复字母的字符串
【发布时间】:2013-01-12 13:20:57
【问题描述】:

有人可以帮我完成这个小任务吗?我需要的是一个存储过程,它可以在表“a”的字符串中找到重复的字母(连续),然后创建一个新表“b”,其中只有具有重复字母的字符串的 id。

类似这样的:

表 A

ID Name   
1  Matt
2  Daave
3  Toom
4  Mike
5  Eddie

从该表中我可以看到DaaveToomEddie 连续有重复的字母,我想创建一个新表并仅列出他们的 ID。类似的东西:

表 B

ID     
2
3
5

只有 2,3,5,因为这是名称中包含重复字母的字符串的 ID。

我希望这是可以理解的,并且非常感谢您的帮助。

【问题讨论】:

  • 马特也有一对字母。您使用的是什么 SQL 引擎?
  • 是的,我的错误,马特也应该包括在内:D 我正在使用 sql server

标签: sql sql-server tsql duplicates letters


【解决方案1】:

在您对存储过程的回答中,您有 2 个错误,一个是列名和 LIKE 子句之间缺少空格,第二个是搜索参数周围缺少单引号。

我首先创建用户定义的标量函数,如果字符串包含重复的字母,则返回 1:

已编辑

CREATE FUNCTION FindDuplicateLetters
(
    @String NVARCHAR(50)
)
RETURNS BIT
AS
BEGIN

    DECLARE @Result BIT = 0 
    DECLARE @Counter INT = 1

    WHILE (@Counter <= LEN(@String) - 1) 
    BEGIN


    IF(ASCII((SELECT SUBSTRING(@String, @Counter, 1))) = ASCII((SELECT SUBSTRING(@String, @Counter + 1, 1))))
        BEGIN
             SET @Result = 1
             BREAK
        END


        SET @Counter = @Counter + 1 
    END

    RETURN @Result

END
GO

函数创建后,只需从简单的SELECT 查询中调用它,如下所示:

SELECT 
    * 
FROM
    (SELECT 
        *, 
        dbo.FindDuplicateLetters(ColumnName) AS Duplicates
    FROM TableName) AS a
WHERE a.Duplicates = 1

使用这种组合,您将只得到具有重复字母的行。

【讨论】:

  • 我试过了:)。 Ty,我是 sql server 的新手,这非常有帮助。现在它可以正常工作了,谢谢大家的帮助。
  • @user2020224 试试上面的函数,它可以处理除排序规则之外的所有字母,因为它比较 ascii 代码。您可以定义要处理的表和列,但您不必指定字母组合。如果这有帮助,请将其标记为答案。
  • 这很棒。我还需要检查连续的字母,所以我编辑检查: IF(ASCII((SELECT SUBSTRING((at)String, (at)Counter, 1))) = ASCII((SELECT SUBSTRING((at)String, ( at)Counter + 1, 1)))-1)
【解决方案2】:

在任何版本的 SQL 中,您都可以通过蛮力方法做到这一点:

select *
from t
where t.name like '%aa%' or
      t.name like '%bb%' or
      . . .
      t.name like '%zz%'

如果您有区分大小写的排序规则,请使用:

where lower(t.name) like '%aa%' or
      . . .

【讨论】:

  • +1 我相信这会很好,但是当你遇到Mr. Töötles 时会发生什么?并不是说它不起作用,SQL Server 可能会将ö 规范化为o,考虑到'%aa%' 等是VARCHAR
【解决方案3】:

虽然这是一篇旧文章,但值得发布一个比蛮力方法或使用标量 udf(通常会降低性能)更快的解决方案。使用NGrams8K 这相当简单。

--sample data
declare @table table (id int identity primary key, [name] varchar(20));
insert @table([name]) values ('Mattaa'),('Daave'),('Toom'),('Mike'),('Eddie');

-- solution #1
select id
from @table
cross apply dbo.NGrams8k([name],1)
where charindex(replicate(token,2), [name]) > 0
group by id;

-- solution #2 (SQL 2012+ solution using LAG)
select id
from
(
  select id, token, prevToken = lag(token,1) over (partition by id order by position)
  from @table
  cross apply dbo.NGrams8k([name],1)
) prep
where token = prevToken
group by id; -- optional id you want to remove possible duplicates. 

【讨论】:

    【解决方案4】:

    这是一种方法。

    首先创建一个数字表

    CREATE TABLE dbo.Numbers
      (
         number INT PRIMARY KEY
      );
    
    INSERT INTO dbo.Numbers
    SELECT number
    FROM   master..spt_values
    WHERE  type = 'P'
           AND number > 0;
    

    然后你就可以使用了

    SELECT *
    FROM   TableA
    WHERE  EXISTS (SELECT *
                   FROM   dbo.Numbers
                   WHERE  number < LEN(Name)
                          AND SUBSTRING(Name, number, 1) = SUBSTRING(Name, number + 1, 1)) 
    

    【讨论】:

      猜你喜欢
      • 2017-09-25
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多