T-SQL에서 중복 공백을 단일 공백으로 바꾸기


100

주어진 필드에 문자 사이에 두 개 이상의 공백이 없는지 확인해야합니다 (모든 공백은 고려하지 않고 공백 만 포함).

그래서

'single    spaces   only'

로 바뀌어야한다

'single spaces only'

아래는 작동하지 않습니다

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

결과적으로

'single  spaces  only'

저는 CLR 기반 솔루션보다 네이티브 T-SQL을 고수하는 것을 선호합니다.

생각?


REGEX 교체로이를 수행 할 수 있습니다.
Raj More

답변:


325

더 깔끔하게 :

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

산출:

단일 공간 선택


6
문자열의 앞과 끝에서 공백을 제거하려는 경우 LTRIM, RTRIM으로 교체하면 자동으로 수행됩니다.
Neil Knight

5
문자열에 <또는> 기호가 많이 포함되지 않는 한. 내 취향에 따라 깨지기 쉬운 것 같습니다.
JohnFx 2010 년

8
정말 우아한 해킹. 찬성. <>가 잠재적으로 입력 텍스트에있는 경우 중간 부분에 두 문자를 사용할 수 있습니다.
richardtallent 2010 년

32
Chris, CHAR (17) 및 CHAR (18)과 같이 인쇄 할 수없는 ASCII 문자를 사용할 수 있습니다. 이러한 문자는 입력 텍스트에 포함되지 않기 때문입니다. 받아 들여지는 대답의 반복보다 여전히 빠릅니다.
richardtallent 2010 년

7
나는 당신이 '> <'를 사용했는지 알아 내기 위해 잠시 이걸 봤어야했는데, ''공백을 바꾸지 않았지만 이제 알았습니다 ... 매우 훌륭합니다. 나는 인쇄 할 수없는 ASCII 문자를 사용하는 @richardtallent 제안과 매우 흡사합니다. 추가 된 조합은 다음을 생성합니다. ) CHAR (17) ',' '),'CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

이것은 작동합니다.

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

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

select @test

1
함수 감싸고 NVARCHAR에 VARCHAR (100)을 변경 (최대)
크리스토프

James와 Neil의 스크립트의 차이점은 James가 while 루프를 통해 실행된다는 것입니다. 개인적인 경험상 테이블의 50,000 개 레코드를 통해 실행하는 것은 매우 느린 경향이 있으므로 프로 시저로 만들고 레코드와 일부를 전달해야합니다. 밴드 새 절차를 만들 수있는 권한이 없을 수 있습니다. 닐의 용도에 따라 기존이 <사용하기 때문에>는 같은 문자열이있는 경우, 기능을 "release < now"당신은 얻을 것이다 "release<><><<><>now", "release<<>now", "release< now"당신이 한 쌍의 하나 하나가 있다면, 그 심볼의 쌍과 같은, 이동할 것
로는 메모리-X

1
50k 레코드를 통해 이것을 실행하는 것은 빠르게 빛날 것입니다. 그것이 당신의 문제라면 다른 문제를 조사 할 것입니다.
user3486773

17

한 행에 특정 수 이상의 공백이 없다는 것을 알고 있다면 바꾸기를 중첩 할 수 있습니다.

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

4 개의 교체는 최대 16 개의 연속 공백을 수정해야합니다 (16, 8, 4, 2, 1).

훨씬 더 길 수 있다면 인라인 함수와 같은 작업을 수행해야합니다.

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

    RETURN @str
END

그럼 그냥

SELECT dbo.strip_spaces(myText) FROM myTable

Brad, 나는 거의 동일한 코드를 가지고 있었지만 당신은 나를 포스트로 이겼습니다. 여러 REPLACE () 호출은 끔찍하지만 예상되는 "추가"공간의 수가 예측 가능하고 상대적으로 작 으면 정상적으로 작동하며 CLR을 통해 RegEx 코드를 호출하지 않는 OP의 요구 사항을 충족합니다.
richardtallent 2010 년

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

바꾸기는 모든 이중 공백에서 작동하므로 여러 번 바꿀 필요가 없습니다. 이것은 세트 기반 솔루션입니다.


이것은 4 칸을 2 칸으로 축소하지 않을까요?
Christoph

나는이 솔루션이 필요를 충족시키지 못한다고 내 질문에 불렀지 만 감사합니다.
Christoph

6

함수를 통해 재귀 적으로 수행 할 수 있습니다.

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

예를 들면 다음과 같습니다.

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

보고:

NewStr
some string with many spaces

또는 @ agdk26 또는 @Neil Knight (그러나 더 안전함)에서 설명한 방법을 기반으로하는 솔루션은
위의 출력을 반환합니다.

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

또는

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

작동 원리 : 여기에 이미지 설명 입력

주의 :
공백을 대체하는 데 사용되는 문자 / 문자열은 문자열의 시작 또는 끝에 존재하지 않아야하며 단독으로 사용되어서는 안됩니다.


1
나는 이것에 대한 재귀 함수의 아이디어를 좋아합니다. 알아야 할 것이 있습니까?
자크 스미스

5

이것은 다소 무차별 적이지만 작동합니다.

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

2

다음은 앞뒤의 공백과 문자열 내의 여러 공백을 정리하기 위해 만든 간단한 함수입니다. 한 번에 최대 약 108 개의 공간과 줄에있는만큼의 블록을 우아하게 처리합니다. 필요한 경우 더 큰 공간 청크가있는 행을 추가하여 8 배로 늘릴 수 있습니다. 빠른 성능으로 보이며 대규모 응용 프로그램에서 일반화 된 사용에도 불구하고 문제를 일으키지 않았습니다.

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

방법 # 1

첫 번째 방법은 단어 사이의 여분의 공백을 임시 마커로 일반적이지 않은 기호 조합으로 바꾸는 것입니다. 그런 다음 루프가 아닌 대체 기능을 사용하여 임시 마커 기호를 대체 할 수 있습니다.

다음은 String 변수 내의 텍스트를 대체하는 코드 예제입니다.

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

실행 시간 테스트 # 1 :이 대체 방법을 10 번 실행했을 때 서버 응답의 평균 대기 시간은 1.7 밀리 초이고 총 실행 시간은 4.6 밀리 초였습니다. 실행 시간 테스트 # 2 : 서버 응답의 평균 대기 시간은 1.7 밀리 초이고 총 실행 시간은 3.7 밀리 초였습니다.

방법 # 2

두 번째 방법은 첫 번째 방법만큼 우아하지는 않지만 작업을 완료합니다. 이 방법은 두 개의 공백을 하나의 공백으로 바꾸는 네 개 (또는 선택적으로 더 많은) replace 문을 중첩하여 작동합니다.

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

실행 시간 테스트 # 1 :이 대체 방법을 10 번 실행했을 때 서버 응답의 평균 대기 시간은 1.9 밀리 초이고 총 실행 시간은 3.8 밀리 초였습니다. 실행 시간 테스트 # 2 : 서버 응답의 평균 대기 시간은 1.8 밀리 초이고 총 실행 시간은 4.8 밀리 초였습니다.

방법 # 3

단어 사이에 여분의 공백을 바꾸는 세 번째 방법은 간단한 루프를 사용하는 것입니다. while 루프에서 여분의 공백을 확인한 다음 replace 함수를 사용하여 루프가 반복 될 때마다 여분의 공백을 줄일 수 있습니다.

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

실행 시간 테스트 # 1 :이 대체 방법을 10 번 실행했을 때 서버 응답의 평균 대기 시간은 1.8 밀리 초이고 총 실행 시간은 3.4 밀리 초였습니다. 실행 시간 테스트 # 2 : 서버 응답의 평균 대기 시간은 1.9 밀리 초이고 총 실행 시간은 2.8 밀리 초였습니다.


1

이것은 모든 문자열에 대해 작동하는 다중 교체를 통한 솔루션입니다 (문자열의 일부가 아닌 특수 문자가 필요하지 않음).

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'

좋은 점,하지만 변화 '아베'에서 '도끼'
아담 Silenko

0

FOR XML PATH 솔루션을 사용하여 하여 여러 공백을 단일 공간으로 바꿉니다.

아이디어는 공백을 XML 태그로 대체 한 다음 XML 문자열을 XML 태그없이 문자열 조각으로 분할하는 것입니다. 마지막으로 둘 사이에 단일 공백 ​​문자를 추가하여 해당 문자열 값을 연결합니다.

최종 UDF 함수를 호출하는 방법은 다음과 같습니다.

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

나는 일반적으로 다음 접근 방식을 사용합니다.

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

0

그냥 다른 방법 추가-

SQL Server에서 REPLACE를 사용하지 않고 여러 공백을 단일 공백으로 바꾸기

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

아래 코드를 찾으십시오

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

이것은 나를 위해 일했습니다 .. 이것이 도움이되기를 바랍니다 ...


-1

이것을 시도 할 수 있습니다.

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

DECLARE @str varchar (150) SET @ str = 'Hello Welcome to World of .net'선택 REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
코드

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

이 시도..


나는이 솔루션이 필요를 충족시키지 못한다고 내 질문에 불렀지 만 감사합니다.
Christoph
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.