[sql] SQL Server에서 선행 0을 트리밍하는 더 나은 기술은 무엇입니까?

내가 사용했던 시간을 위해 :

SUBSTRING(str_col, PATINDEX('%[^0]%', str_col), LEN(str_col))

그러나 최근에는 ‘0’이 아닌 문자가 일치하지 않기 때문에 ‘00000000’과 같은 모든 “0”문자가있는 열에서 문제를 발견했습니다.

내가 본 대안 기술은 다음과 TRIM같습니다.

REPLACE(LTRIM(REPLACE(str_col, '0', ' ')), ' ', '0')

공백이 다시 “0”으로 바뀌면 공백이 “0”으로 바뀌기 때문에 임베드 된 공백이 있으면 문제가 있습니다.

스칼라 UDF를 피하려고합니다. SQL Server 2005에서 UDF와 관련된 많은 성능 문제를 발견했습니다.



답변

SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col))


답변

왜 값을 캐스트 INTEGER한 다음에 다시 돌려 보내지 VARCHAR않겠습니까?

SELECT  CAST(CAST('000000000' AS INTEGER) AS VARCHAR)

--------
       0


답변

모두 0 (또는 단일 0)이있는 경우 고려하지 않는 다른 대답.
일부는 항상 빈 문자열을 0으로 기본 설정합니다. 빈 문자열로 유지해야 할 때 잘못되었습니다.
원래 질문을 다시 읽으십시오. 이것은 질문자가 원하는 것에 응답합니다.

해결책 # 1 :

--This example uses both Leading and Trailing zero's.
--Avoid losing those Trailing zero's and converting embedded spaces into more zeros.
--I added a non-whitespace character ("_") to retain trailing zero's after calling Replace().
--Simply remove the RTrim() function call if you want to preserve trailing spaces.
--If you treat zero's and empty-strings as the same thing for your application,
--  then you may skip the Case-Statement entirely and just use CN.CleanNumber .
DECLARE @WackadooNumber VarChar(50) = ' 0 0123ABC D0 '--'000'--
SELECT WN.WackadooNumber, CN.CleanNumber,
       (CASE WHEN WN.WackadooNumber LIKE '%0%' AND CN.CleanNumber = '' THEN '0' ELSE CN.CleanNumber END)[AllowZero]
 FROM (SELECT @WackadooNumber[WackadooNumber]) AS WN
 OUTER APPLY (SELECT RTRIM(RIGHT(WN.WackadooNumber, LEN(LTRIM(REPLACE(WN.WackadooNumber + '_', '0', ' '))) - 1))[CleanNumber]) AS CN
--Result: "123ABC D0"

솔루션 # 2 (샘플 데이터 포함) :

SELECT O.Type, O.Value, Parsed.Value[WrongValue],
       (CASE WHEN CHARINDEX('0', T.Value)  > 0--If there's at least one zero.
              AND LEN(Parsed.Value) = 0--And the trimmed length is zero.
             THEN '0' ELSE Parsed.Value END)[FinalValue],
       (CASE WHEN CHARINDEX('0', T.Value)  > 0--If there's at least one zero.
              AND LEN(Parsed.TrimmedValue) = 0--And the trimmed length is zero.
             THEN '0' ELSE LTRIM(RTRIM(Parsed.TrimmedValue)) END)[FinalTrimmedValue]
  FROM 
  (
    VALUES ('Null', NULL), ('EmptyString', ''),
           ('Zero', '0'), ('Zero', '0000'), ('Zero', '000.000'),
           ('Spaces', '    0   A B C '), ('Number', '000123'),
           ('AlphaNum', '000ABC123'), ('NoZero', 'NoZerosHere')
  ) AS O(Type, Value)--O is for Original.
  CROSS APPLY
  ( --This Step is Optional.  Use if you also want to remove leading spaces.
    SELECT LTRIM(RTRIM(O.Value))[Value]
  ) AS T--T is for Trimmed.
  CROSS APPLY
  ( --From @CadeRoux's Post.
    SELECT SUBSTRING(O.Value, PATINDEX('%[^0]%', O.Value + '.'), LEN(O.Value))[Value],
           SUBSTRING(T.Value, PATINDEX('%[^0]%', T.Value + '.'), LEN(T.Value))[TrimmedValue]
  ) AS Parsed

결과 :

MikeTeeVee_SQL_Server_Remove_Leading_Zeros

요약:

선행 제로를 일회성 제거하기 위해 위의 내용을 사용할 수 있습니다.
많이 재사용하려는 경우 ITVF (Inline-Table-Valued-Function)에 배치하십시오.
UDF의 성능 문제에 대한 귀하의 우려는 이해할 수 있습니다.
그러나이 문제는 All-Scalar-Functions 및 Multi-Statement-Table-Function에만 적용됩니다.
ITVF를 사용하는 것은 완벽합니다.

타사 데이터베이스와 동일한 문제가 있습니다.
영숫자 필드를 사용하면 많은 사람들이 선행 공백없이 입력됩니다.
따라서 누락 된 선행 0을 정리하지 않고 결합 할 수 없습니다.

결론:

선행 0을 제거하는 대신 조인을 수행 할 때 잘린 값을 선행 0으로 채우는 것이 좋습니다.
더 좋은 방법은 선행 0을 추가 한 다음 인덱스를 다시 작성하여 테이블의 데이터를 정리하는 것입니다.
나는 이것이 더 빠르고 덜 복잡하다고 생각합니다.

SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF(' 0A10  ', ''))), 10)--0000000A10
SELECT RIGHT('0000000000' + LTRIM(RTRIM(NULLIF('', ''))), 10)--NULL --When Blank.


답변

공백 대신 0을 일반적으로 열 텍스트에 포함되지 않아야하는 ‘희귀 한’공백 문자로 바꿉니다. 줄 바꿈은 아마도 이와 같은 열에 충분할 것입니다. 그런 다음 LTrim을 정상적으로 수행하고 특수 문자를 다시 0으로 바꿀 수 있습니다.


답변

문자열이 완전히 0으로 구성된 경우 다음은 ‘0’을 반환합니다.

CASE WHEN SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col)) = '' THEN '0' ELSE SUBSTRING(str_col, PATINDEX('%[^0]%', str_col+'.'), LEN(str_col)) END AS str_col


답변

이것은 좋은 기능을 만듭니다 ….

DROP FUNCTION [dbo].[FN_StripLeading]
GO
CREATE FUNCTION [dbo].[FN_StripLeading] (@string VarChar(128), @stripChar VarChar(1))
RETURNS VarChar(128)
AS
BEGIN
-- http://stackoverflow.com/questions/662383/better-techniques-for-trimming-leading-zeros-in-sql-server
    DECLARE @retVal VarChar(128),
            @pattern varChar(10)
    SELECT @pattern = '%[^'+@stripChar+']%'
    SELECT @retVal = CASE WHEN SUBSTRING(@string, PATINDEX(@pattern, @string+'.'), LEN(@string)) = '' THEN @stripChar ELSE SUBSTRING(@string, PATINDEX(@pattern, @string+'.'), LEN(@string)) END
    RETURN (@retVal)
END
GO
GRANT EXECUTE ON [dbo].[FN_StripLeading] TO PUBLIC


답변

문자열이 숫자이면 캐스트 (값은 정수)는 항상 작동합니다