programing

T-SQL을 사용하여 하위 문자열의 마지막 항목 색인 찾기

bestprogram 2023. 4. 7. 22:00

T-SQL을 사용하여 하위 문자열의 마지막 항목 색인 찾기

SQL을 사용하여 문자열의 마지막 오카렌스 인덱스를 쉽게 찾을 수 있는 방법이 있습니까?SQL Server 2000 입니다.이치노 물 netSystem.String.LastIndexOf방법은 다음과 같습니다.약간의 구글링을 통해 이 마지막 인덱스 검색 기능이 확인되었지만, "텍스트" 열 식을 전달하면 작동하지 않습니다.다른 곳에서 발견된 다른 솔루션은 검색 중인 텍스트의 길이가 1자일 때만 작동합니다.

나는 함수를 만들어야 할 것 같아.그러면 제가 여기에 올려서 여러분들이 보고 활용할 수 있도록 하겠습니다.

직설적인 방법?아뇨, 하지만 그 반대도 써봤어요.말 그대로.

이전 루틴에서는 특정 문자열의 마지막 발생을 찾기 위해 REVERSE() 함수를 사용하고 CHARINDEX에 이어 다시 REVERSE에 이어 원래 순서를 복원했습니다.예:

SELECT
   mf.name
  ,mf.physical_name
  ,reverse(left(reverse(physical_name), charindex('\', reverse(physical_name)) -1))
 from sys.master_files mf

는 서브폴더에 얼마나 깊이 중첩되어 있는지에 관계없이 실제 데이터베이스 파일명을 "물리적 이름"에서 추출하는 방법을 보여 줍니다.이렇게 하면 하나의 문자(백슬래시)만 검색되지만 이 문자를 기반으로 더 긴 검색 문자열을 작성할 수 있습니다.

유일한 단점은 이것이 TEXT 데이터 유형에서 얼마나 잘 작동할지 모른다는 것입니다.SQL 2005를 사용한 지 몇 년이 지났습니다만, TEXT를 사용하는 것은 서툴러졌습니다만, 왼쪽과 오른쪽을 사용할 수 있는 것 같습니다.

필립

가장 간단한 방법은...

REVERSE(SUBSTRING(REVERSE([field]),0,CHARINDEX('[expr]',REVERSE([field]))))

Sqlserver 2005를 합니다.REVERSE함수는 여러 번 퍼포먼스에 악영향을 미칩니다.아래 코드가 더 효율적입니다.

DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'

-- text before last slash
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath))) AS Before
-- text after last slash
SELECT RIGHT(@FilePath, CHARINDEX(@FindChar,REVERSE(@FilePath))-1) AS After
-- the position of the last slash
SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) + 1 AS LastOccuredAt

텍스트 데이터 유형의 함수는 작은 목록으로 제한됩니다.

할 수 것은 '로 하는 것'밖에.PATINDEXㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, DATALENGTH-1, DATALENGTH-2, DATALENGTH-3제로로 때까지(합니다(DATALENGH-DATALENGH).

...SQL Server 2000도저히 감당할 수 없어

기타 답변에 대한 편집: SQL Server 2000에서 텍스트 데이터와 함께 사용할 수 있는 함수 목록에 REVERSE가 없습니다.

DECLARE @FilePath VARCHAR(50) = 'My\Super\Long\String\With\Long\Words'
DECLARE @FindChar VARCHAR(1) = '\'

SELECT LEN(@FilePath) - CHARINDEX(@FindChar,REVERSE(@FilePath)) AS LastOccuredAt

오래되었지만 여전히 유효한 질문입니다. 그래서 여기 다른 사람들이 제공한 정보를 바탕으로 제가 만든 것입니다.

create function fnLastIndexOf(@text varChar(max),@char varchar(1))
returns int
as
begin
return len(@text) - charindex(@char, reverse(@text)) -1
end
REVERSE(SUBSTRING(REVERSE(ap_description),CHARINDEX('.',REVERSE(ap_description)),len(ap_description)))  

나에게 더 잘했다

이것은 나에게 매우 효과가 있었다.

REVERSE(SUBSTRING(REVERSE([field]), CHARINDEX(REVERSE('[expr]'), REVERSE([field])) + DATALENGTH('[expr]'), DATALENGTH([field])))

음, 오래된 스레드인 것은 알지만 SQL2000(또는 다른 데이터베이스)에서는 집계 테이블이 이 작업을 수행할 수 있습니다.

DECLARE @str CHAR(21),
        @delim CHAR(1)
 SELECT @str = 'Your-delimited-string',
        @delim = '-'

SELECT
    MAX(n) As 'position'
FROM
    dbo._Tally
WHERE
    substring(@str, _Tally.n, 1) = @delim

집계표는 숫자의 증가표일 뿐입니다.

substring(@str, _Tally.n, 1) = @delim각 딜리미터의 위치를 가져오면 해당 세트의 최대 위치만 얻을 수 있습니다.

집계표 정말 멋지다.지금까지 사용해 본 적이 없는 경우는 SQL Server Central에 관한 좋은 기사가 있습니다.

됨 *편집:삭제됨n <= LEN(TEXT_FIELD)TEXT LEN()으로 지정합니다.★★★★★★만 있으면,substring(...) = @delim결과는 아직 맞지만 그대로입니다.

이 답변은 MS SQL Server 2008(MS SQL Server 2000에 액세스 할 수 없습니다)을 사용하고 있습니다만, OP에 의한 견해는 3가지 상황을 고려해야 합니다.제가 시도한 내용으로는, 여기에서는 답변이 없습니다.이 세 가지를 모두 커버하고 있습니다.

  1. 지정된 문자열에서 검색 문자의 마지막 인덱스를 반환합니다.
  2. 지정된 문자열에서 검색 하위 문자열의 마지막 인덱스(1자 이상)를 반환합니다.
  3. 또는 반환됩니다.0

제가 생각해낸 함수는 두 가지 파라미터가 있습니다.

@String NVARCHAR(MAX)할 : " " " "

@FindString NVARCHAR(MAX): 의 문자 중 @String

「」가 됩니다.INT은 '' 중 입니다.@FindString@String ★★★★★★★★★★★★★★★★★」0라는 의미입니다.@FindString 없다@String

다음은 함수의 기능에 대한 설명입니다.

  1. @ReturnVal로로 합니다.0 나타내다@FindString 없다@String
  2. 합니다.@FindString@String를 사용하여CHARINDEX()
  3. @FindString@String0,@ReturnVal0
  4. @FindString@String> 0,@FindString@String해 줍니다.@FindString@String를 사용하여REVERSE()
  5. @ReturnVal이거나 양수이며, 이 는 ㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴ.@FindString@String ★★★★★★★★★★★★★★★★★」0 나타내다@FindString 없다@String

작성 함수 스크립트(복사 및 붙여넣기 준비 완료)는 다음과 같습니다.

CREATE FUNCTION [dbo].[fn_LastIndexOf] 
(@String NVARCHAR(MAX)
, @FindString NVARCHAR(MAX))
RETURNS INT
AS 
BEGIN
    DECLARE @ReturnVal INT = 0
    IF CHARINDEX(@FindString,@String) > 0
        SET @ReturnVal = (SELECT LEN(@String) - 
        (CHARINDEX(REVERSE(@FindString),REVERSE(@String)) + 
        LEN(@FindString)) + 2)  
    RETURN @ReturnVal
END

다음은 기능을 편리하게 테스트할 수 있는 간단한 예입니다.

DECLARE @TestString NVARCHAR(MAX) = 'My_sub2_Super_sub_Long_sub1_String_sub_With_sub_Long_sub_Words_sub2_'
, @TestFindString NVARCHAR(MAX) = 'sub'

SELECT dbo.fn_LastIndexOf(@TestString,@TestFindString)

다른 버전에 액세스할 수 없기 때문에 MS SQL Server 2008에서만 이 버전을 실행했지만, 제가 조사한 바로는 적어도 2008년 이상에는 이 버전을 사용할 수 있을 것입니다.

즐거운 시간 되세요.

문자열과 하위 문자열을 모두 반전시킨 다음 첫 번째 항목을 검색합니다.

문자열의 마지막 공백 인덱스를 가져오려면 이 식 RIGHT(이름, (CHARINDEX(' ' ' ' ' ' ' ' ' ' , REVERCE(name , 0 ))를 사용하여 문자열의 마지막 단어를 반환합니다.이름 및/또는 중간 이름의 이니셜을 포함하는 전체 이름의 성을 구문 분석하는 경우 유용합니다.

다른 응답 중 일부는 실제 문자열을 반환하지만 실제 인덱스 int를 알아야 했습니다.그리고 그렇게 하는 답변들은 일을 너무 복잡하게 만드는 것 같다.다른 대답들을 참고해서, 나는 다음과 같이 했다.

먼저 함수를 만들었습니다.

CREATE FUNCTION [dbo].[LastIndexOf] (@stringToFind varchar(max), @stringToSearch varchar(max))
RETURNS INT
AS
BEGIN
    RETURN (LEN(@stringToSearch) - CHARINDEX(@stringToFind,REVERSE(@stringToSearch))) + 1
END
GO

그런 다음 쿼리에서 다음을 수행할 수 있습니다.

declare @stringToSearch varchar(max) = 'SomeText: SomeMoreText: SomeLastText'

select dbo.LastIndexOf(':', @stringToSearch)

위는 23(':'의 마지막 인덱스)을 반환해야 합니다.

이걸로 누군가 좀 더 쉬웠으면 좋겠네요!

몇 년 된 질문인 건 알지만...

- 그래, 아니에요! - 왜요?Access 2010, 를 사용할 수 있습니다.InStrRev()이 일을 하기 위해서.이게 도움이 됐으면 좋겠다.

비효율적일 거라는 건 알지만, 그 영화 캐스팅을 고려해본 적 있나요?text까지 수비하다.varchar당신이 찾은 웹사이트에서 제공하는 솔루션을 사용할 수 있도록?이 솔루션에서는 문제가 발생한다는 것을 알고 있습니다.이 경우 레코드가 절단될 수 있습니다.text필드 길이가 넘쳤습니다.varchar(물론 퍼포먼스는 그다지 좋지 않습니다).

데이터가 내부에 있기 때문에text[ ] 필드(및 SQL Server 2000을 사용하고 있는 경우)에는 옵션이 제한됩니다.

@indexOf = <whatever characters you are searching for in your string>

@LastIndexOf = LEN([MyField]) - CHARINDEX(@indexOf, REVERSE([MyField]))

테스트하지 않았습니다. 인덱스가 0이기 때문에 1씩 꺼질 수 있지만, 다음에서 작동합니다.SUBSTRING@indexOf

SUBSTRING([MyField], 0, @LastIndexOf)

이 코드는 서브스트링에 여러 문자가 포함되어 있는 경우에도 기능합니다.

DECLARE @FilePath VARCHAR(100) = 'My_sub_Super_sub_Long_sub_String_sub_With_sub_Long_sub_Words'
DECLARE @FindSubstring VARCHAR(5) = '_sub_'

-- Shows text before last substing
SELECT LEFT(@FilePath, LEN(@FilePath) - CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) - LEN(@FindSubstring) + 1) AS Before
-- Shows text after last substing
SELECT RIGHT(@FilePath, CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) -1) AS After
-- Shows the position of the last substing
SELECT LEN(@FilePath) - CHARINDEX(REVERSE(@FindSubstring), REVERSE(@FilePath)) AS LastOccuredAt

폴더 경로에서 백슬래시의 마지막 n번째 위치를 찾아야 했습니다.제 해결책은 이렇습니다.

/*
http://stackoverflow.com/questions/1024978/find-index-of-last-occurrence-of-a-sub-string-using-t-sql/30904809#30904809
DROP FUNCTION dbo.GetLastIndexOf
*/
CREATE FUNCTION dbo.GetLastIndexOf
(
  @expressionToFind         VARCHAR(MAX)
  ,@expressionToSearch      VARCHAR(8000)
  ,@Occurrence              INT =  1        -- Find the nth last 
)
RETURNS INT
AS
BEGIN

    SELECT  @expressionToSearch = REVERSE(@expressionToSearch)

    DECLARE @LastIndexOf        INT = 0
            ,@IndexOfPartial    INT = -1
            ,@OriginalLength    INT = LEN(@expressionToSearch)
            ,@Iteration         INT = 0

    WHILE (1 = 1)   -- Poor man's do-while
    BEGIN
        SELECT @IndexOfPartial  = CHARINDEX(@expressionToFind, @expressionToSearch)

        IF (@IndexOfPartial = 0) 
        BEGIN
            IF (@Iteration = 0) -- Need to compensate for dropping out early
            BEGIN
                SELECT @LastIndexOf = @OriginalLength  + 1
            END
            BREAK;
        END

        IF (@Occurrence > 0)
        BEGIN
            SELECT @expressionToSearch = SUBSTRING(@expressionToSearch, @IndexOfPartial + 1, LEN(@expressionToSearch) - @IndexOfPartial - 1)
        END

        SELECT  @LastIndexOf = @LastIndexOf + @IndexOfPartial
                ,@Occurrence = @Occurrence - 1
                ,@Iteration = @Iteration + 1

        IF (@Occurrence = 0) BREAK;
    END

    SELECT @LastIndexOf = @OriginalLength - @LastIndexOf + 1 -- Invert due to reverse
    RETURN @LastIndexOf 
END
GO

GRANT EXECUTE ON GetLastIndexOf TO public
GO

여기 합격 사례들이 있습니다.

SELECT dbo.GetLastIndexOf('f','123456789\123456789\', 1) as indexOf -- expect 0 (no instances)
SELECT dbo.GetLastIndexOf('\','123456789\123456789\', 1) as indexOf -- expect 20
SELECT dbo.GetLastIndexOf('\','123456789\123456789\', 2) as indexOf -- expect 10
SELECT dbo.GetLastIndexOf('\','1234\6789\123456789\', 3) as indexOf -- expect 5

전에 (''만 해당NVARCHAR DATALENGTH★★★★★★★★★★★★★★★★★★:

DECLARE @Fullstring NVARCHAR(30) = '12.345.67890.ABC';

DECLARE @Delimiter CHAR(1) = '.';

SELECT SUBSTRING(@Fullstring, 1, DATALENGTH(@Fullstring)/2 - CHARINDEX(@Delimiter, REVERSE(@Fullstring)));

이 답변은 OP의 요구 사항을 충족합니다. 구체적으로는 바늘이 1자 이상일 수 있으며 건초더미에서 바늘이 발견되지 않을 때 오류를 발생시키지 않습니다.내가 보기에 다른 대부분의 답변은 그러한 엣지 케이스를 다루지 않는 것 같았다.또한 MS SQL Server의 네이티브 CharIndex 함수에 의해 제공되는 "Starting Position" 인수를 추가하였습니다.CharIndex의 사양은 왼쪽에서 왼쪽이 아닌 오른쪽에서 왼쪽으로 처리하려고 했습니다.예: 바늘 또는 건초 더미가 null이면 null을 반환하고 건초 더미에서 바늘이 발견되지 않으면 0을 반환합니다.한 가지 회피할 수 없었던 점은 내장 기능으로 세 번째 파라미터가 옵션이라는 것입니다.SQL Server 사용자 정의 함수에서는 함수가 "EXEC"를 사용하여 호출되지 않는 한 모든 파라미터를 호출로 제공해야 합니다.세 번째 파라미터는 파라미터 목록에 포함되어야 하지만 값을 지정하지 않고 해당 파라미터의 자리 표시자로 키워드 "default"를 지정할 수 있습니다(아래 예 참조).이 기능에서 세 번째 파라미터를 삭제하는 것이 필요 없는 경우보다 쉽기 때문에 필요에 따라 추가하는 것이 더 쉽기 때문에 여기에 시작점으로 포함시켰습니다.

create function dbo.lastCharIndex(
 @needle as varchar(max),
 @haystack as varchar(max),
 @offset as bigint=1
) returns bigint as begin
 declare @position as bigint
 if @needle is null or @haystack is null return null
 set @position=charindex(reverse(@needle),reverse(@haystack),@offset)
 if @position=0 return 0
 return (len(@haystack)-(@position+len(@needle)-1))+1
end
go

select dbo.lastCharIndex('xyz','SQL SERVER 2000 USES ANSI SQL',default) -- returns 0
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',default) -- returns 27
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',1) -- returns 27
select dbo.lastCharIndex('SQL','SQL SERVER 2000 USES ANSI SQL',11) -- returns 1

는 같은 유사한 에 대한 알게 되었습니다.REVERSE★★★★★★ 。

이 경우 구문이 약간 다른 OpenEdge(Progress) 데이터베이스용입니다.이 때문에,INSTR대부분의 Oracle 유형 데이터베이스가 제공하는 기능을 사용할 수 있습니다.

그래서 저는 다음과 같은 코드를 생각해 냈습니다.

SELECT 
  INSTR(foo.filepath, '/',1, LENGTH(foo.filepath) - LENGTH( REPLACE( foo.filepath, '/',  ''))) AS IndexOfLastSlash 
FROM foo

그러나 특정 상황(OpenEdge(Progress) 데이터베이스)에서는 문자를 빈 문자로 대체하면 원래 문자열과 길이가 같기 때문에 원하는 동작이 되지 않았습니다.이것은 별로 납득이 가지 않지만, 이하의 코드로 문제를 회피할 수 있었습니다.

SELECT 
  INSTR(foo.filepath, '/',1, LENGTH( REPLACE( foo.filepath, '/',  'XX')) - LENGTH(foo.filepath))  AS IndexOfLastSlash 
FROM foo

코드로는 T-SQL의 문제를 해결할 수 없다는 것을 알게 되었습니다. 왜냐하면 T-SQL에는 다른 대안이 없기 때문입니다.INSTR「」를 Occurence★★★★★★★★★★★★★★★★★★.

이 스칼라 함수를 작성하기 위해 필요한 코드를 추가하여 위의 예시와 동일하게 사용할 수 있도록 하겠습니다.

  -- Drop the function if it already exists
  IF OBJECT_ID('INSTR', 'FN') IS NOT NULL
    DROP FUNCTION INSTR
  GO

  -- User-defined function to implement Oracle INSTR in SQL Server
  CREATE FUNCTION INSTR (@str VARCHAR(8000), @substr VARCHAR(255), @start INT, @occurrence INT)
  RETURNS INT
  AS
  BEGIN
    DECLARE @found INT = @occurrence,
            @pos INT = @start;

    WHILE 1=1 
    BEGIN
        -- Find the next occurrence
        SET @pos = CHARINDEX(@substr, @str, @pos);

        -- Nothing found
        IF @pos IS NULL OR @pos = 0
            RETURN @pos;

        -- The required occurrence found
        IF @found = 1
            BREAK;

        -- Prepare to find another one occurrence
        SET @found = @found - 1;
        SET @pos = @pos + 1;
    END

    RETURN @pos;
  END
  GO

것을 , 「이것들」이 「이것들」의 에.REVERSE함수를 사용할 수 있습니다.이 스칼라 함수를 작성할 필요가 없습니다.필요한 결과는 다음과 같습니다.

SELECT
  LEN(foo.filepath) - CHARINDEX('/', REVERSE(foo.filepath))+1 AS LastIndexOfSlash 
FROM foo

1글자 이상의 길이를 찾는 것을 처리합니다.원하시면 팜사이즈를 늘려주세요.

투고를 거부할 수 없었다

drop function if exists lastIndexOf
go 
create function lastIndexOf(@searchFor varchar(100),@searchIn varchar(500))
returns int
as
begin 

if LEN(@searchfor) > LEN(@searchin) return 0 
declare @r varchar(500), @rsp varchar(100)
select @r = REVERSE(@searchin)
select @rsp = REVERSE(@searchfor)
return len(@searchin) - charindex(@rsp, @r) - len(@searchfor)+1
end 

및 테스트

select dbo.lastIndexof('greg','greg greg asdflk; greg sadf' )  -- 18
select dbo.lastIndexof('greg','greg greg asdflk; grewg sadf' )  --5
select dbo.lastIndexof(' ','greg greg asdflk; grewg sadf' ) --24

이 실은 꽤 오래되었다.예를 들어 다양한 근거를 포함하는 솔루션을 제시하겠습니다.

declare @aStringData varchar(100) = 'The quick brown/fox jumps/over the/lazy dog.pdf'
/*
The quick brown/fox jumps/over the/lazy dog.pdf
fdp.god yzal/eht revo/spmuj xof/nworb kciuq ehT
*/

select
    Len(@aStringData) - CharIndex('/', Reverse(@aStringData)) + 1 [Char Index],
    -- Get left side of character, without the character '/'
    Left(@aStringData, Len(@aStringData) - CharIndex('/', Reverse(@aStringData))) [Left excluding char],
    -- Get left side of character, including the character '/'
    Left(@aStringData, Len(@aStringData) - CharIndex('/', Reverse(@aStringData)) + 1) [Left including char],
    -- Get right side of character, without the character '/'
    Right(@aStringData, CharIndex('/', Reverse(@aStringData)) - 1) [Right including char]

char 위치를 가져오려면 CharIndex가 첫 번째 항목을 가져오므로 문자열을 반전해야 합니다.CharIndex 커서가 발견된 캐릭터의 반대편에 위치한다는 것을 기억하십시오.따라서 문자열의 왼쪽 또는 오른쪽 부분을 얻으려면 -1 또는 +1만큼 보정해야 합니다.

언급URL : https://stackoverflow.com/questions/1024978/find-index-of-last-occurrence-of-a-sub-string-using-t-sql