Sql server 查找并删除重复的子字符串

Sql server 查找并删除重复的子字符串,sql-server,sql-server-2008,tsql,Sql Server,Sql Server 2008,Tsql,我在SQLServer2008表中有一列,其中部分字符串意外重复 有没有人有一个快速简单的方法来删除尾部重复的子字符串 比如说, alpha\bravo\charlie\delta\charlie\delta 应该是 alpha\bravo\charlie\delta 如果您还没有数字表: SET NOCOUNT ON; DECLARE @UpperLimit INT; SET @UpperLimit = 4000; WITH n(rn) AS ( SELECT ROW_NUMBE

我在SQLServer2008表中有一列,其中部分字符串意外重复

有没有人有一个快速简单的方法来删除尾部重复的子字符串

比如说,

alpha\bravo\charlie\delta\charlie\delta
应该是

alpha\bravo\charlie\delta

如果您还没有数字表:

SET NOCOUNT ON;
DECLARE @UpperLimit INT;
SET @UpperLimit = 4000;

WITH n(rn) AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY [object_id])
    FROM sys.all_columns
)
SELECT [Number] = rn - 1
INTO dbo.Numbers FROM n
WHERE rn <= @UpperLimit + 1;

CREATE UNIQUE CLUSTERED INDEX n ON dbo.Numbers([Number]);
示例用法:

SELECT dbo.DedupeString('alpha\bravo\bravo\charlie\delta\bravo\charlie\delta');
结果:

alpha\bravo\charlie\delta
你也可以这样说:

UPDATE dbo.MessedUpTable
  SET OopsColumn = dbo.DedupeString(OopsColumn);
@MikaelEriksson可能会用一种更有效的方法来使用XML消除重复项,但这是我在此之前可以提供的:-

create function RemoveDups(@S nvarchar(max)) returns nvarchar(max)
as
begin
  declare @R nvarchar(max)
  declare @W nvarchar(max)
  set @R = ''

  while len(@S) > 1
  begin
    -- Get the first word
    set @W = left(@S, charindex('/', @S+'/')-1)

    -- Add word to result if not already added
    if '/'+@R not like '%/'+@W+'/%'
    begin
      set @R = @R + @W + '/'
    end 

    -- Remove first word
    set @S = stuff(@S, 1, charindex('/', @S+'/'), '')
  end

  return left(@R, len(@R)- 1)
end
应秘书长的要求。然而,我不会就什么是最快的执行提出任何要求

-- Table to replace in
declare @T table
(
  ID int identity,
  Value nvarchar(max)
)

-- Add some sample data
insert into @T values ('alpha/beta/alpha/gamma/delta/gamma/delta/alpha')
insert into @T values ('delta/beta/alpha/beta/alpha/gamma/delta/gamma/delta/alpha')

-- Update the column
update T
set Value = NewValue
from (
       select T1.ID,
              Value,
              stuff((select '/' + T4.Value
                     from (
                            select T3.X.value('.', 'nvarchar(max)') as Value,
                                   row_number() over(order by T3.X) as rn
                            from T2.X.nodes('/x') as T3(X)
                          ) as T4
                     group by T4.Value
                     order by min(T4.rn)
                     for xml path(''), type).value('.',  'nvarchar(max)'), 1, 1, '') as NewValue
       from @T as T1
         cross apply (select cast('<x>'+replace(T1.Value, '/', '</x><x>')+'</x>' as xml)) as T2(X)
     ) as T

select *
from @T  

我假设您也要消除多个重复,例如source=alpha\bravo\alpha\bravo\alpha变为alpha\bravo?是否也要查找重复项,以及是整个字符串还是较大字符串中的子字符串?@TonyHopkinson:示例是整个字符串,而不是较大字符串的一部分。复制的长度会有所不同,例如ABCDBCD->ABCD.Oops。否我添加了常规行走字符串:。我将考虑一下XML的内容。我还添加了一个XML版本。要保留单词的顺序有点棘手。但是我不认为使用XML来拆分字符串比数字表更有效。我知道这是一篇比较老的帖子,但这让我很开心!
create function RemoveDups(@S nvarchar(max)) returns nvarchar(max)
as
begin
  declare @R nvarchar(max)
  declare @W nvarchar(max)
  set @R = ''

  while len(@S) > 1
  begin
    -- Get the first word
    set @W = left(@S, charindex('/', @S+'/')-1)

    -- Add word to result if not already added
    if '/'+@R not like '%/'+@W+'/%'
    begin
      set @R = @R + @W + '/'
    end 

    -- Remove first word
    set @S = stuff(@S, 1, charindex('/', @S+'/'), '')
  end

  return left(@R, len(@R)- 1)
end
-- Table to replace in
declare @T table
(
  ID int identity,
  Value nvarchar(max)
)

-- Add some sample data
insert into @T values ('alpha/beta/alpha/gamma/delta/gamma/delta/alpha')
insert into @T values ('delta/beta/alpha/beta/alpha/gamma/delta/gamma/delta/alpha')

-- Update the column
update T
set Value = NewValue
from (
       select T1.ID,
              Value,
              stuff((select '/' + T4.Value
                     from (
                            select T3.X.value('.', 'nvarchar(max)') as Value,
                                   row_number() over(order by T3.X) as rn
                            from T2.X.nodes('/x') as T3(X)
                          ) as T4
                     group by T4.Value
                     order by min(T4.rn)
                     for xml path(''), type).value('.',  'nvarchar(max)'), 1, 1, '') as NewValue
       from @T as T1
         cross apply (select cast('<x>'+replace(T1.Value, '/', '</x><x>')+'</x>' as xml)) as T2(X)
     ) as T

select *
from @T