Zastąp zduplikowane spacje pojedynczą spacją w T-SQL

100

Muszę się upewnić, że dane pole nie ma więcej niż jednej spacji (nie przejmuję się wszystkimi spacjami, tylko spacjami) między znakami.

Więc

'single    spaces   only'

należy zamienić na

'single spaces only'

Poniższe nie będą działać

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

jak by to skutkowało

'single  spaces  only'

Naprawdę wolałbym trzymać się natywnego T-SQL zamiast rozwiązania opartego na CLR.

Myśli?

Christoph
źródło
Możesz to zrobić, zastępując REGEX
Raj More

Odpowiedzi:

326

Jeszcze porządniej:

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

Wynik:

wybierz pojedyncze przestrzenie

Neil Knight
źródło
6
Jeśli chcesz usunąć spacje z przodu i na końcu ciągu, zawiń zastąpienie w LTRIM, RTRIM i zrobi to za Ciebie.
Neil Knight
5
O ile twój ciąg nie zawiera wielu znaków <lub>. Wydaje się kruche jak na mój gust.
JohnFx
8
Naprawdę elegancki hack. Głosowano za. Dowolne dwa znaki mogą być użyte jako środkowa część, jeśli <> są potencjalnie w tekście wejściowym.
richardtallent
32
Chris, możesz używać niedrukowalnych znaków ASCII, takich jak CHAR (17) i CHAR (18), ponieważ NIGDY nie będą one znajdować się w tekście wejściowym. Jeszcze szybciej niż zapętlenie zaakceptowanej odpowiedzi.
richardtallent
7
Musiałem naprawdę przez chwilę się temu przyjrzeć, aby dowiedzieć się, że użyłeś '> ​​<', '' Bez zamiany spacji, ale teraz, kiedy to rozumiem ... jest bardzo genialny. Bardzo podobała mi się sugestia @richardtallent dotycząca użycia niedrukowalnych znaków ASCII, których dodana kombinacja daje: REPLACE (REPLACE (REPLACE (LastName, '', 'CHAR (17) CHAR (18)'), 'CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs
25

To zadziała:

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

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

select @test
James Wiseman
źródło
1
Zawijanie funkcji i zmiana varchar (100) na nvarchar (max)
Christoph
Różnica między skryptami Jamesa i Neila polega na tym, że James uruchamia pętlę while, która z własnego doświadczenia wynika, że ​​uruchomienie jej przez 50 000 rekordów tabeli jest bardzo powolne, więc musisz utworzyć ją jako procedurę i przekazać rekord, a niektóre zlecenia, możesz nie mieć uprawnień do tworzenia zespołu nowej procedury. Zastosowania Neila za istniejące funkcje, ponieważ używa <>, jeśli ciąg jak "release < now"wtedy dostaniesz "release<><><<><>now", "release<<>now", "release< now", jego samo z każdej pary symboli, jeśli masz ani jednej pary to będzie poruszać
Memor-X
1
Przepuszczanie tego przez 50k rekordów powinno być błyskawiczne, przyjrzę się innym problemom, jeśli to jest twój problem.
user3486773
17

Jeśli wiesz, że nie będzie więcej niż pewna liczba spacji w rzędzie, możesz po prostu zagnieździć zastąpienie:

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

4 zmiany powinny naprawić do 16 kolejnych odstępów (16, potem 8, potem 4, potem 2, potem 1)

Gdyby mógł być znacznie dłuższy, musiałbyś wykonać coś w rodzaju funkcji in-line:

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

    RETURN @str
END

Następnie po prostu zrób

SELECT dbo.strip_spaces(myText) FROM myTable
BradC
źródło
Brad, miałem prawie identyczny kod, ale pokonałeś mnie do Post, więc zagłosuj. Wiele wywołań REPLACE () jest hackerskich, ale jeśli liczba oczekiwanych „dodatkowych” spacji jest przewidywalna i stosunkowo niewielka, to wystarczy i spełni wymóg OP, aby nie wywoływać kodu RegEx przez CLR.
richardtallent
6
update mytable
set myfield = replace (myfield, '  ',  ' ')
where charindex('  ', myfield) > 0 

Zastąp będzie działać na wszystkich podwójnych spacjach, bez konieczności wielokrotnego zastępowania. To jest rozwiązanie oparte na zestawie.

HLGEM
źródło
Czy nie spowodowałoby to zwinięcia 4 spacji w 2?
Christoph,
W swoich pytaniach nazwałem to rozwiązanie jako nie spełniające potrzeby, ale dzięki.
Christoph,
6

Można to zrobić rekurencyjnie za pomocą funkcji:

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

wtedy na przykład:

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

zwroty:

NewStr
some string with many spaces

Lub rozwiązanie oparte na metodzie opisanej przez @ agdk26 lub @Neil Knight (ale bezpieczniejsze)
oba przykłady zwracają wynik powyżej:

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...

lub

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

Jak to działa: wprowadź opis obrazu tutaj

Uwaga:
znak / ciąg używany do zastępowania spacji nie powinien występować na początku ani na końcu ciągu i powinien być samodzielny.

Adam Silenko
źródło
1
Podoba mi się idea funkcji rekurencyjnej. czy jest coś, o czym należy wiedzieć?
Zach Smith,
5

To trochę brutalna siła, ale zadziała

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
JohnFx
źródło
2

Oto prosta funkcja, którą stworzyłem do czyszczenia wszelkich spacji przed lub po, oraz wielu spacji w ciągu. Z wdziękiem obsługuje do około 108 miejsc w jednym naciągu i tyle bloków, ile jest w sznurku. Możesz zwiększyć ten współczynnik o współczynnik 8, dodając dodatkowe linie z większymi fragmentami spacji, jeśli zajdzie taka potrzeba. Wydaje się, że działa szybko i nie powodował żadnych problemów pomimo ogólnego zastosowania w dużej aplikacji.

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
Robert Petolillo
źródło
1

Znalazłem to podczas szukania odpowiedzi:

SELECT REPLACE(
        REPLACE(
             REPLACE(
                LTRIM(RTRIM('1 2  3   4    5     6'))
            ,'  ',' '+CHAR(7))
        ,CHAR(7)+' ','')
    ,CHAR(7),'') AS CleanString
where charindex('  ', '1 2  3   4    5     6') > 0

Pełną odpowiedź (z wyjaśnieniem) pobrano z: http://techtipsbysatish.blogspot.com/2010/08/sql-server-replace-multiple-spaces-with.html

Przy drugim spojrzeniu wydaje się, że jest to tylko nieco inna wersja wybranej odpowiedzi.

Żołnierz angielski
źródło
1

Metoda nr 1

Pierwsza metoda polega na zastąpieniu dodatkowych spacji między słowami nietypową kombinacją symboli jako tymczasowy znacznik. Następnie możesz zastąpić tymczasowe symbole znaczników za pomocą funkcji replace zamiast pętli.

Oto przykład kodu, który zastępuje tekst w zmiennej String.

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

Test czasu wykonywania nr 1: W dziesięciu uruchomieniach tej metody zastępczej średni czas oczekiwania na odpowiedzi serwera wyniósł 1,7 milisekundy, a całkowity czas wykonania wyniósł 4,6 milisekundy. Test czasu wykonywania nr 2: średni czas oczekiwania na odpowiedzi serwera wyniósł 1,7 milisekundy, a całkowity czas wykonania wyniósł 3,7 milisekundy.

Metoda nr 2

Druga metoda nie jest tak elegancka jak pierwsza, ale również wykonuje zadanie. Ta metoda działa poprzez zagnieżdżenie czterech (lub opcjonalnie więcej) instrukcji zamiany, które zastępują dwie spacje jedną spacją.

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

Test czasu wykonywania nr 1: W dziesięciu uruchomieniach tej metody zastępczej średni czas oczekiwania na odpowiedzi serwera wyniósł 1,9 milisekundy, a całkowity czas wykonania 3,8 milisekundy. Test czasu wykonywania nr 2: średni czas oczekiwania na odpowiedzi serwera wyniósł 1,8 milisekundy, a całkowity czas wykonania - 4,8 milisekundy.

Metoda nr 3

Trzecią metodą zastępowania dodatkowych spacji między słowami jest użycie prostej pętli. Możesz sprawdzić dodatkowe spacje w pętli while, a następnie użyć funkcji replace w celu zmniejszenia dodatkowych spacji przy każdej iteracji pętli.

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

Test czasu wykonywania nr 1: W dziesięciu uruchomieniach tej metody zastępczej średni czas oczekiwania na odpowiedzi serwera wyniósł 1,8 milisekundy, a całkowity czas wykonania 3,4 milisekundy. Test czasu wykonywania nr 2: średni czas oczekiwania na odpowiedzi serwera wyniósł 1,9 milisekundy, a całkowity czas wykonania 2,8 milisekundy.


źródło
1

Jest to rozwiązanie polegające na wielokrotnym zastępowaniu, które działa dla dowolnych ciągów (nie wymaga znaków specjalnych, które nie są częścią ciągu).

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'
agdk26
źródło
fajna rzecz, ale zmiana „abe” na „ax”
Adam Silenko 11.04.2016
0

Używam rozwiązania FOR XML PATH, aby zamienić wiele spacji w jedną

Pomysł polega na zastąpieniu spacji znacznikami XML Następnie podziel ciąg XML na fragmenty bez znaczników XML Na koniec konkatenację tych wartości ciągów poprzez dodanie pojedynczych znaków spacji pomiędzy dwoma

Oto jak można wywołać ostateczną funkcję UDF

select dbo.ReplaceMultipleSpaces('   Sample   text  with  multiple  space     ')
Eralper
źródło
0
 DECLARE @str varchar(150)
SET @str='Hello    My   name  is Jiyaul   mustafa'
Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{',''),'{}',' ')
Kod
źródło
0

Zwykle używam tego podejścia:

declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')
Matthys Du Toit
źródło
0

Wystarczy dodać inną metodę

Zastąpienie wielu przestrzeni pojedynczą spacją BEZ użycia REPLACE w SQL Server-

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 !
*/
Arulmouzhi
źródło
0

Proszę znaleźć poniższy kod

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

To zadziałało dla mnie ... Mam nadzieję, że to pomoże ...

Lekhnath Pandey
źródło
-1

Możesz spróbować tego:

select Regexp_Replace('single    spaces   only','( ){2,}', ' ') from dual;
karthika harisankar
źródło
DECLARE @str varchar (150) SET @ str = 'Witaj, witaj w świecie .net' Wybierz REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
Kod
-3
update mytable
set myfield = replace(myfield, '  ',  ' ')
where myfield like '%  %'

Spróbuj tego..

Henz
źródło
W swoich pytaniach nazwałem to rozwiązanie jako nie spełniające potrzeby, ale dzięki.
Christoph,