7

I have the following strings

KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52
IYT_2012_CBBI1_S_66_2012-09-21_15_28_53

I want to extract everything after the 1st _ & before the 5th _

ex:

2012_CBBE2_E_12704 
2012_CBBI1_S_66
1
  • thanks friends, ' SUBSTRING(FileName, 5, LEN(FileName) - 4 - 20) AS CUSDEC ' Commented Nov 22, 2012 at 5:22

3 Answers 3

8

Method 1. Nested CHARINDEX calls.

Use CHARINDEX('_', stringvalue) to get the position of the first _ in stringvalue. You can instruct CHARINDEX to start searching from a certain position, if you pass that position as the third argument:

CHARINDEX(`_`, stringvalue, startpos)

Now, if the starting position will be the result of CHARINDEX('_', stringvalue)+1, i.e. like this:

CHARINDEX(`_`, stringvalue, CHARINDEX(`_`, stringvalue) + 1)

then that will give you the second _'s position. So, to find the fifth _, you'll need to nest CHARINDEX three more times:

WITH aTable AS (
  SELECT
    *
  FROM
    (VALUES
      ('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52'),
      ('IYT_2012_CBBI1_S_66_2012-09-21_15_28_53')
    ) AS v (aStringColumn)
),
positions AS (
  SELECT
    aStringColumn,
    Underscore1 = CHARINDEX('_', aStringColumn),
    Underscore5 = CHARINDEX('_',
                            aStringColumn,
                            CHARINDEX('_',
                                      aStringColumn,
                                      CHARINDEX('_',
                                                aStringColumn,
                                                CHARINDEX('_',
                                                          aStringColumn,
                                                          CHARINDEX('_',
                                                                    aStringColumn
                                                                   ) + 1
                                                         ) + 1
                                               ) + 1
                                     ) + 1
                           )
  FROM
    aTable
)
SELECT
  aSubstring = SUBSTRING(aStringColumn,
                         Underscore1 + 1,
                         Underscore5 - Underscore1 - 1
                        )
FROM
  positions
;

Method 2. Character split + ranking.

  1. Use a numbers table to split every string into single characters, pulling their positions along the way.

  2. Rank every character's occurrence in the string.

  3. Get two subsets:

    1) with the character _ and the ranking of 1;

    2) with the character _ and the ranking of 5.

    Join these subsets with each other.

  4. Use the corresponding positions of _ #1 and _ #5 similarly to Method 1 to get the substring(s).

WITH aTable AS (
  SELECT
    *
  FROM
    (VALUES
      ('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52'),
      ('IYT_2012_CBBI1_S_66_2012-09-21_15_28_53')
    ) AS v (aStringColumn)
),
split AS (
  SELECT
    t.aStringColumn,
    aChar    = SUBSTRING(t.aStringColumn, n.Number, 1),
    Position = n.Number
  FROM
    aTable t
    INNER JOIN Numbers n
      ON n.Number BETWEEN 1 AND LEN(t.aStringColumn)
),
ranked AS (
  SELECT
    *,
    rnk = ROW_NUMBER() OVER (PARTITION BY aStringColumn, aChar ORDER BY Position)
  FROM
    split
  WHERE
    aChar = '_'
)
SELECT
  aSubstring = SUBSTRING(first.aStringColumn,
                         first.Position + 1,
                         fifth.Position - first.Position - 1
                        )
FROM
  ranked first
  INNER JOIN ranked fifth
    ON first.aStringColumn = fifth.aStringColumn
WHERE
  first.rnk = 1
  AND fifth.rnk = 5
;

Note: both methods assume that every aStringColumn value does have at least 5 underscore characters.

Sign up to request clarification or add additional context in comments.

1 Comment

SUBSTRING(FileName, 5, LEN(FileName) - 4 - 20) AS err
5

You can use the SUBSTRING function to extract a sub string from a given string.

SELECT SUBSTRING('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52', 6, 18);

1 Comment

Can't use substring function because length will change "KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52"
1

It's cunningly named SubString

as in

Select Substring('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52',6,18)

If you want to find it within the string, then CharIndex would be useful. Are you sure you want to do this in SQL, it's going to be messy and slow and you'll need to create a UDF, or use CLR to make any real use of it.

1 Comment

As in Select MyMiddleBit([SomeValue]) From SomeTable ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.