7

我有以下字符串

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

我想在 1 号_之后和 5 号之前提取所有内容_

前任:

2012_CBBE2_E_12704 
2012_CBBI1_S_66
4

3 回答 3

8

方法 1. 嵌套 CHARINDEX 调用。

用于获取 中第一个的位置。如果您将该位置作为第三个参数传递,您可以指示从某个位置开始搜索:CHARINDEX('_', stringvalue)_stringvalueCHARINDEX

CHARINDEX(`_`, stringvalue, startpos)

现在,如果起始位置将是 的结果,即像这样:CHARINDEX('_', stringvalue)+1

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

那么这会给你第二个_的位置。因此,要找到第五个_,您需要再嵌套CHARINDEX三次:

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
;

方法二、人物分割+排名。

  1. 使用数字表将每个字符串拆分为单个字符,沿途拉动它们的位置。

  2. 对字符串中每个字符的出现进行排名。

  3. 获取两个子集:

    1)人物_和排名为1;

    2) 具有5的角色_和排名。

    将这些子集相互连接。

  4. 与方法1类似,使用_#1和#5的对应位置来获取子字符串。_

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
;

注意:这两种方法都假定每个aStringColumn值都至少有 5 个下划线字符。

于 2012-11-21T18:42:36.750 回答
5

您可以使用SUBSTRING函数从给定字符串中提取子字符串。

SELECT SUBSTRING('KLPI_2012_CBBE2_E_12704_2012-09-21_13_59_52', 6, 18);
于 2012-11-21T09:44:57.777 回答
1

它被巧妙地命名为 SubString

如在

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

如果您想在字符串中找到它,那么 CharIndex 会很有用。您确定要在 SQL 中执行此操作吗,它会变得混乱且缓慢,您需要创建一个 UDF,或者使用 CLR 来真正使用它。

于 2012-11-21T09:47:13.633 回答