T-SQL'de yinelenen boşlukları tek boşlukla değiştirin


102

Belirli bir alanda karakterler arasında birden fazla boşluk olmadığından emin olmam gerekir (tüm beyaz boşluklar, sadece boşluk).

Yani

'single    spaces   only'

dönüştürülmesi gerekiyor

'single spaces only'

Aşağıdakiler işe yaramayacak

select replace('single    spaces   only','  ',' ')

sonuçlanacağı gibi

'single  spaces  only'

CLR tabanlı bir çözüm yerine yerel T-SQL'e bağlı kalmayı gerçekten tercih ederim.

Düşünceler?


Bunu bir REGEX değiştirme ile yapabilirsiniz
Raj More

Yanıtlar:


329

Daha da düzenli:

select string = replace(replace(replace(' select   single       spaces',' ','<>'),'><',''),'<>',' ')

Çıktı:

tek boşlukları seçin


6
Dizenin önündeki ve sonundaki boşlukları kaldırmak istiyorsanız, değiştirmeyi bir LTRIM, RTRIM'e sarın ve sizin için yapacaktır.
Neil Knight

7
Diziniz çok fazla <veya> işareti içermediği sürece. Hoşuma göre kırılgan görünüyor.
JohnFx

8
Gerçekten zarif bir hack. Olumlu oy verildi. Girdi metninde <> bulunuyorsa, orta kısım için herhangi iki karakter kullanılabilir.
richardtallent

32
Chris, CHAR (17) ve CHAR (18) gibi yazdırılamayan ASCII karakterlerini kullanabilirsin, çünkü bunlar ASLA girdi metninde olmayacak. Yine de kabul edilen cevabın döngüsünden daha hızlı.
richardtallent

7
'> <', '' Yer değiştirme yok ama şimdi anladığıma göre ... çok zekice. @Richardtallent'in, eklenen kombinasyonu aşağıdakileri üreten yazdırılamayan ASCII karakterlerini kullanma önerisini çok beğendim: REPLACE (REPLACE (REPLACE (LastName, '', 'CHAR (17) CHAR (18)'), 'CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

Bu işe yarar:

declare @test varchar(100)
set @test = 'this   is  a    test'

while charindex('  ',@test  ) > 0
begin
   set @test = replace(@test, '  ', ' ')
end

select @test

1
Fonksiyona sarma ve varchar (100) 'ü nvarchar (maks) olarak değiştirme
Christoph

James'in ve Neil'in senaryoları arasındaki fark, James, kişisel deneyimde, bir tablonun 50.000 kaydının çalışmasına rağmen, çok yavaş olma eğiliminde olduğu için, döngü halindeyken koşmasıdır, bu nedenle, onu bir prosedür olarak oluşturmanız ve bir kaydı ve bazılarını geçirmeniz gerekir. işler yeni bir grup prosedürü oluşturma iznine sahip olmayabilirsiniz. Neil'in kullanımları başına varolan o <kullanması nedeniyle> Eğer gibi bir dize varsa, işlevleri "release < now"o zaman alırsınız "release<><><<><>now", "release<<>now", "release< now"sen çiftinin tek biri varsa, onun simgelerinin herhangi çifti ile aynı, o zaman hareket edecek
Memor-X

1
Bunu 50 bin kayıtta çalıştırmak çok hızlı olmalı, eğer sorununuz buysa başka konulara bakardım.
user3486773

17

Bir satırda belirli sayıda boşluk olmayacağını biliyorsanız, sadece değiştirmeyi iç içe geçirebilirsiniz:

replace(replace(replace(replace(myText,'  ',' '),'  ',' '),'  ',' '),'  ',' ')

4 yer değiştirme, en fazla 16 ardışık boşluk düzeltmelidir (16, sonra 8, sonra 4, sonra 2, sonra 1)

Önemli ölçüde daha uzun olsaydı, satır içi işlev gibi bir şey yapmanız gerekir:

CREATE FUNCTION strip_spaces(@str varchar(8000))
RETURNS varchar(8000) AS
BEGIN 
    WHILE CHARINDEX('  ', @str) > 0 
        SET @str = REPLACE(@str, '  ', ' ')

    RETURN @str
END

O zaman sadece yap

SELECT dbo.strip_spaces(myText) FROM myTable

Brad, neredeyse aynı kodum vardı ama beni postada yendin, o yüzden oy ver. Birden çok REPLACE () çağrısı hack'lidir, ancak beklenen "fazladan" boşlukların sayısı tahmin edilebilir ve nispeten küçükse, bu gayet iyi olacak ve OP'nin CLR aracılığıyla RegEx kodunu çağırmama gerekliliğini karşılayacaktır.
richardtallent

6
update mytable
set myfield = replace (myfield, '  ',  ' ')
where charindex('  ', myfield) > 0 

Değiştir, tüm çift boşluklarda çalışır, birden fazla yer değiştirmeye gerek yoktur. Bu, set tabanlı çözümdür.


Bu 4 boşluğu 2'ye indirmez mi?
Christoph

Bu çözümü sorularımda ihtiyacı karşılamıyor diye çağırdım ama teşekkürler.
Christoph

6

İşlev aracılığıyla özyinelemeli olarak yapılabilir:

CREATE FUNCTION dbo.RemSpaceFromStr(@str VARCHAR(MAX)) RETURNS VARCHAR(MAX) AS
BEGIN
  RETURN (CASE WHEN CHARINDEX('  ', @str) > 0 THEN
    dbo.RemSpaceFromStr(REPLACE(@str, '  ', ' ')) ELSE @str END);
END

sonra, örneğin:

SELECT dbo.RemSpaceFromStr('some   string    with         many     spaces') AS NewStr

İadeler:

NewStr
some string with many spaces

Veya @ agdk26 veya @Neil Knight (ancak daha güvenli) tarafından açıklanan yönteme dayalı çözüm,
her iki örnek de yukarıdaki çıktıyı döndürür:

SELECT REPLACE(REPLACE(REPLACE('some   string    with         many     spaces'
  , '  ', ' ' + CHAR(7)), CHAR(7) + ' ', ''), ' ' + CHAR(7), ' ') AS NewStr 
--but it remove CHAR(7) (Bell) from string if exists...

veya

SELECT REPLACE(REPLACE(REPLACE('some   string    with         many     spaces'
  , '  ', ' ' + CHAR(7) + CHAR(7)), CHAR(7) + CHAR(7) + ' ', ''), ' ' + CHAR(7) + CHAR(7), ' ') AS NewStr
--but it remove CHAR(7) + CHAR(7) from string

Nasıl çalışır: görüntü açıklamasını buraya girin

Dikkat:
Boşlukları değiştirmek için kullanılan karakter / dizge dizenin başında veya sonunda bulunmamalı ve tek başına bağımsız olmalıdır.


1
Bunun için özyinelemeli işlev fikrini seviyorum. dikkat edilmesi gereken bir şey var mı?
Zach Smith

5

Bu biraz kaba kuvvet ama işe yarayacak

CREATE FUNCTION stripDoubleSpaces(@prmSource varchar(max)) Returns varchar(max)
AS 
BEGIN
    WHILE (PATINDEX('%  %', @prmSource)>0)
     BEGIN
        SET @prmSource = replace(@prmSource  ,'  ',' ')
     END

    RETURN @prmSource
END

GO

-- Unit test -- 
PRINT dbo.stripDoubleSpaces('single    spaces   only')

single spaces only

3

İşte önceki veya sonraki boşlukları ve bir dizedeki birden fazla boşluğu temizlemek için oluşturduğum basit bir işlev. Tek bir uzantıda yaklaşık 108 boşluğu ve dizede olduğu kadar çok bloğu incelikle işler. Gerekirse daha büyük boşluklar içeren ek satırlar ekleyerek bunu 8 kat artırabilirsiniz. Hızlı bir şekilde çalışıyor gibi görünüyor ve büyük bir uygulamada genelleştirilmiş kullanımına rağmen herhangi bir soruna neden olmadı.

CREATE FUNCTION [dbo].[fnReplaceMultipleSpaces] (@StrVal AS VARCHAR(4000)) 
RETURNS VARCHAR(4000) 
AS 
BEGIN

    SET @StrVal = Ltrim(@StrVal)
    SET @StrVal = Rtrim(@StrVal)

    SET @StrVal = REPLACE(@StrVal, '                ', ' ')  -- 16 spaces
    SET @StrVal = REPLACE(@StrVal, '        ', ' ')  -- 8 spaces
    SET @StrVal = REPLACE(@StrVal, '    ', ' ')  -- 4 spaces
    SET @StrVal = REPLACE(@StrVal, '  ', ' ')  -- 2 spaces
    SET @StrVal = REPLACE(@StrVal, '  ', ' ')  -- 2 spaces (for odd leftovers)

RETURN @StrVal

END


1

Yöntem 1

İlk yöntem, sözcükler arasındaki fazladan boşlukları, geçici bir işaretçi olarak yaygın olmayan bir sembol kombinasyonuyla değiştirmektir. Daha sonra geçici işaret sembollerini döngü yerine değiştirme işlevini kullanarak değiştirebilirsiniz.

Burada, bir String değişkeni içindeki metni değiştiren bir kod örneği verilmiştir.

DECLARE @testString AS VARCHAR(256) = ' Test        text   with  random*        spacing. Please normalize  this spacing!';
SELECT REPLACE(REPLACE(REPLACE(@testString, ' ', '*^'), '^*', ''), '*^', ' ');

Yürütme Süresi Testi # 1: Bu değiştirme yönteminin on çalıştırmasında, sunucu yanıtlarında ortalama bekleme süresi 1,7 milisaniye ve toplam yürütme süresi 4,6 milisaniye idi. Yürütme Süresi Testi # 2: Sunucu yanıtlarında ortalama bekleme süresi 1,7 milisaniye ve toplam yürütme süresi 3,7 milisaniye idi.

Yöntem 2

İkinci yöntem, birincisi kadar zarif değil, aynı zamanda işi de yaptırıyor. Bu yöntem, iki boş alanı bir boşlukla değiştiren dört (veya isteğe bağlı olarak daha fazla) deyimi iç içe yerleştirerek çalışır.

DECLARE @testString AS VARCHAR(256) = ' Test        text   with  random*        spacing. Please normalize  this spacing!';
SELECT REPLACE(REPLACE(REPLACE(REPLACE(@testString,' ',' '),' ',' '),' ',' '),' ',' ')

Yürütme Süresi Testi # 1: Bu değiştirme yönteminin on çalıştırmasında, sunucu yanıtlarında ortalama bekleme süresi 1,9 milisaniye ve toplam yürütme süresi 3,8 milisaniye idi. Yürütme Süresi Testi # 2: Sunucu yanıtlarında ortalama bekleme süresi 1,8 milisaniye ve toplam yürütme süresi 4,8 milisaniye idi.

Yöntem 3

Kelimeler arasındaki fazladan boşlukları değiştirmenin üçüncü yöntemi, basit bir döngü kullanmaktır. Bir while döngüsündeki fazladan boşlukları kontrol edebilir ve ardından döngünün her yinelemesinde fazladan boşlukları azaltmak için değiştirme işlevini kullanabilirsiniz.

DECLARE @testString AS VARCHAR(256) = ' Test text with random* spacing. Please normalize this spacing!';
WHILE CHARINDEX(' ',@testString) > 0
SET @testString = REPLACE(@testString, ' ', ' ')
SELECT @testString

Yürütme Süresi Testi # 1: Bu değiştirme yönteminin on çalıştırmasında, sunucu yanıtlarında ortalama bekleme süresi 1,8 milisaniye ve toplam yürütme süresi 3,4 milisaniye idi. Yürütme Süresi Testi # 2: Sunucu yanıtlarında ortalama bekleme süresi 1,9 milisaniye ve toplam yürütme süresi 2,8 milisaniye idi.


1

Bu, herhangi bir dizge için çalışan çoklu değiştirme yoluyla çözümdür (dizenin parçası olmayan özel karakterlere ihtiyaç duymaz).

declare @value varchar(max)
declare @result varchar(max)
set @value = 'alpha   beta gamma  delta       xyz'

set @result = replace(replace(replace(replace(replace(replace(replace(
  @value,'a','ac'),'x','ab'),'  ',' x'),'x ',''),'x',''),'ab','x'),'ac','a')

select @result -- 'alpha beta gamma delta xyz'

Güzel bir şey, ama değişen 'Abe' için 'balta'
Adam Silenko

0

Birden çok boşluğu tek alana değiştirmek için FOR XML PATH çözümünü kullanıyorum

Buradaki fikir, boşlukları XML etiketleriyle değiştirmektir.Sonra XML dizesini XML etiketleri olmadan dize parçalarına ayırmak Son olarak, bu dize değerlerini, ikisi arasına tek boşluk karakterleri ekleyerek birleştirmektir.

İşte son UDF işlevi nasıl çağrılabilir

select dbo.ReplaceMultipleSpaces('   Sample   text  with  multiple  space     ')

0
 DECLARE @str varchar(150)
SET @str='Hello    My   name  is Jiyaul   mustafa'
Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{',''),'{}',' ')

0

Genelde şu yaklaşımı kullanırım:

declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')

0

Sadece Başka Bir Yöntem Eklemek-

SQL Server'da DEĞİŞTİRME KULLANMADAN Birden Çok Alanı Tek Boşlukla Değiştirme-

DECLARE @TestTable AS TABLE(input VARCHAR(MAX));

INSERT INTO @TestTable VALUES
('HAPPY         NEWYEAR     2020'),
('WELCOME       ALL     !');

SELECT
    CAST('<r><![CDATA[' + input + ']]></r>' AS XML).value('(/r/text())[1] cast as xs:token?','VARCHAR(MAX)')
    AS Expected_Result
FROM @TestTable;

--OUTPUT
/*
Expected_Result
HAPPY NEWYEAR 2020
WELCOME ALL !
*/

0

Lütfen aşağıdaki kodu bulun

select trim(string_agg(value,' ')) from STRING_SPLIT('  single    spaces   only  ',' ')
where value<>' '

Bu benim için çalıştı .. Umarım bu yardımcı olur ...


-1

Bunu deneyebilirsiniz:

select Regexp_Replace('single    spaces   only','( ){2,}', ' ') from dual;

DECLARE @str varchar (150) SET @ str = 'Merhaba .net Dünyasına Hoş Geldiniz' DEĞİŞTİR'i seçin (DEĞİŞTİR (DEĞİŞTİR (@str, '', '{}'), '} {', ''), '{ } ',' ')
Kod

-3
update mytable
set myfield = replace(myfield, '  ',  ' ')
where myfield like '%  %'

Bunu dene..


Bu çözümü sorularımda ihtiyacı karşılamıyor diye çağırdım ama teşekkürler.
Christoph
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.