47

I need a SQL query to get the value between two known strings (the returned value should start and end with these two strings).

An example.

"All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought."

In this case the known strings are "the dog" and "immediately". So my query should return "the dog had been very bad and required harsh punishment immediately"

I've come up with this so far but to no avail:

SELECT SUBSTRING(@Text, CHARINDEX('the dog', @Text), CHARINDEX('immediately', @Text))

@Text being the variable containing the main string.

Can someone please help me with where I'm going wrong?

4

16 回答 16

62

The problem is that the second part of your substring argument is including the first index. You need to subtract the first index from your second index to make this work.

SELECT SUBSTRING(@Text, CHARINDEX('the dog', @Text)
, CHARINDEX('immediately',@text) - CHARINDEX('the dog', @Text) + Len('immediately'))
于 2013-08-21T16:33:32.133 回答
20

I think what Evan meant was this:

SELECT SUBSTRING(@Text, CHARINDEX(@First, @Text) + LEN(@First), 
                 CHARINDEX(@Second, @Text) - CHARINDEX(@First, @Text) - LEN(@First))
于 2013-08-21T16:36:43.700 回答
19

An example is this: You have a string and the character $

String :

aaaaa$bbbbb$ccccc

Code:

SELECT SUBSTRING('aaaaa$bbbbb$ccccc',CHARINDEX('$','aaaaa$bbbbb$ccccc')+1, CHARINDEX('$','aaaaa$bbbbb$ccccc',CHARINDEX('$','aaaaa$bbbbb$ccccc')+1) -CHARINDEX('$','aaaaa$bbbbb$ccccc')-1) as My_String

Output:

bbbbb
于 2016-05-11T11:12:34.970 回答
8

I had a similar need to parse out a set of parameters stored within an IIS logs' csUriQuery field, which looked like this: id=3598308&user=AD\user&parameter=1&listing=No needed in this format.

I ended up creating a User-defined function to accomplish a string between, with the following assumptions:

  1. If the starting occurrence is not found, a NULL is returned, and
  2. If the ending occurrence is not found, the rest of the string is returned

Here's the code:

CREATE FUNCTION dbo.str_between(@col varchar(max), @start varchar(50), @end varchar(50))  
  RETURNS varchar(max)  
  WITH EXECUTE AS CALLER  
AS  
BEGIN  
  RETURN substring(@col, charindex(@start, @col) + len(@start), 
         isnull(nullif(charindex(@end, stuff(@col, 1, charindex(@start, @col)-1, '')),0),
         len(stuff(@col, 1, charindex(@start, @col)-1, ''))+1) - len(@start)-1);
END;  
GO

For the above question, the usage is as follows:

DECLARE @a VARCHAR(MAX) = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
SELECT dbo.str_between(@a, 'the dog', 'immediately')
-- Yields' had been very bad and required harsh punishment '
于 2018-02-06T21:14:52.907 回答
7

You need to adjust for the LENGTH in the SUBSTRING. You were pointing it to the END of the 'ending string'.

Try something like this:

declare @TEXT varchar(200)
declare @ST varchar(200)
declare @EN varchar(200)
set @ST = 'the dog'
set @EN = 'immediately'
set @TEXT = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
SELECT SUBSTRING(@Text, CHARINDEX(@ST, @Text), (CHARINDEX(@EN, @Text)+LEN(@EN))-CHARINDEX(@ST, @Text))

Of course, you may need to adjust it a bit.

于 2013-08-21T16:03:33.717 回答
6

Try this and replace '[' & ']' with your string

SELECT SUBSTRING(@TEXT,CHARINDEX('[',@TEXT)+1,(CHARINDEX(']',@TEXT)-CHARINDEX('[',@TEXT))-1)
于 2015-03-27T13:21:19.277 回答
5

I have a feeling you might need SQL Server's PATINDEX() function. Check this out:

Usage on Patindex() function

So maybe:

SELECT SUBSTRING(@TEXT, PATINDEX('%the dog%', @TEXT), PATINDEX('%immediately%',@TEXT))
于 2013-08-21T16:08:00.870 回答
5
SELECT 
SUBSTRING( '123@yahoo.com',  charindex('@','123@yahoo.com',1) + 1, charindex('.','123@yahoo.com',1) - charindex('@','123@yahoo.com',1) - 1 )
于 2016-05-16T13:49:23.783 回答
2
DECLARE @Text VARCHAR(MAX), @First VARCHAR(MAX), @Second VARCHAR(MAX)
SET @Text = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'
SET @First = 'the dog'
SET @Second = 'immediately'

SELECT SUBSTRING(@Text, CHARINDEX(@First, @Text), 
                 CHARINDEX(@Second, @Text) - CHARINDEX(@First, @Text) + LEN(@Second))
于 2013-08-21T16:26:22.307 回答
2

You're getting the starting position of 'punishment immediately', but passing that in as the length parameter for your substring.

You would need to substract the starting position of 'the dog' from the charindex of 'punishment immediately', and then add the length of the 'punishment immediately' string to your third parameter. This would then give you the correct text.

Here's some rough, hacky code to illustrate the process:

DECLARE @text VARCHAR(MAX)
SET @text = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'

DECLARE @start INT
SELECT @start = CHARINDEX('the dog',@text)

DECLARE @endLen INT
SELECT @endLen = LEN('immediately')

DECLARE @end INT
SELECT @end = CHARINDEX('immediately',@text)
SET @end = @end - @start + @endLen

SELECT @end

SELECT SUBSTRING(@text,@start,@end)

Result: the dog had been very bad and required harsh punishment immediately

于 2013-08-21T16:39:00.600 回答
0

Hope this helps : Declared a variable , in case of any changes need to be made thats only once .

declare @line  varchar(100)

set @line ='Email_i-Julie@mail.com'

select SUBSTRING(@line ,(charindex('-',@line)+1), CHARINDEX('@',@line)-charindex('-',@line)-1)
于 2016-09-23T23:05:10.263 回答
0
DECLARE @text VARCHAR(MAX)

SET @text = 'All I knew was that the dog had been very bad and required harsh punishment immediately regardless of what anyone else thought.'

DECLARE @pretext AS nvarchar(100) = 'the dog'    
DECLARE @posttext AS nvarchar(100) = 'immediately'

SELECT 
    CASE 
        WHEN CHARINDEX(@posttext, @Text) - (CHARINDEX(@pretext, @Text) + len(@pretext)) < 0 
            THEN ''
            ELSE SUBSTRING(@Text, 
                           CHARINDEX(@pretext, @Text) + LEN(@pretext),   
                           CHARINDEX(@posttext, @Text) - (CHARINDEX(@pretext, @Text) + LEN(@pretext)))    
    END AS betweentext  
于 2017-02-22T11:48:37.970 回答
0
SELECT SUBSTRING('aaaaa$bbbbb$ccccc',instr('aaaaa$bbbbb$ccccc','$',1,1)+1, instr('aaaaa$bbbbb$ccccc','$',1,2)-1) -instr('aaaaa$bbbbb$ccccc','$',1,1)) as My_String
于 2019-02-05T09:34:18.003 回答
0

I needed to get (099) 0000111-> (099) | 0000111 like two different columns.

SELECT 
    SUBSTRING(Phone, CHARINDEX('(', Phone) + 0, (2 + ((LEN(Phone)) - CHARINDEX(')', REVERSE(Phone))) - CHARINDEX('(', Phone))) AS CodePhone,
    LTRIM(SUBSTRING(Phone, CHARINDEX(')', Phone) + 1, LEN(Phone))) AS NumberPhone
FROM 
    Suppliers
WHERE 
    Phone LIKE '%(%)%'
于 2022-02-15T20:32:15.433 回答
-1
select substring(@string,charindex('@first',@string)+1,charindex('@second',@string)-(charindex('@first',@string)+1))
于 2020-10-05T13:03:18.527 回答
-1

Let us consider we have a string DUMMY_DATA_CODE_FILE and we want to find out the substring between 2nd and 3rd underscore(_). Then we use query something like this.

select  SUBSTRING('DUMMY_DATA_CODE_FILE',charindex('_', 'DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE', 1))+1)+1, (charindex('_', 'DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE',  (charindex('_','DUMMY_DATA_CODE_FILE', 1))+1))+1)- charindex('_', 'DUMMY_DATA_CODE_FILE', (charindex('_','DUMMY_DATA_CODE_FILE', 1))+1)-1)) as Code
于 2021-05-05T13:46:57.523 回答