Извлечение части строки со сложным шаблоном SQL

#sql #sql-server #string #function #wildcard

#sql #sql-сервер #строка #функция #подстановочный знак

Вопрос:

Я работаю со строкой, как показано ниже:

 DOT LTB TOL SP BLM 3X(35X**25.1**GR)BWY BNL
  

И я пытаюсь извлечь значение с плавающей запятой между последним X и G -> 25.1 .

В Python это простая задача с использованием регулярного выражения: **[0-9] X([0-9.] )G**

Но я не смог найти способ извлечь данные здесь, в SQL Server:

Я попытался написать функцию, которая определяет позицию X и ) аргумент следующим образом:

 AS
Begin

    Declare @LastX as INT
    Declare @LastG as INT
    Declare @Diff as INT
    Declare @Result as varchar(50)
    Set @LastX = LEN(@Temp) - CAST(CHARINDEX('X', REVERSE(@Temp)) AS Integer) 
    Set @LastG = LEN(@Temp) - CAST(CHARINDEX(')', REVERSE(@Temp)) AS Integer)
    Set @Diff = @LastG - @LastX
    IF @Diff > 0
        Set @Result = SUBSTRING(@Temp, @LastX, @Diff)
    ELSE
        Set @Result = 0
    
    Return @Result
End
  

Мой результат 5X25.1G

Можете ли вы помочь мне с этим?

Я также открыт, если у вас есть другие предложения по извлечению этого значения в SQL.

Комментарии:

1. Подсказка, вы хотите PATINDEX найти положение шаблонов, а не CHARINDEX то, которое находит положение символов.

2. В более новых версиях sql server вы также можете выполнить скрипт на Python

3. возможно, это может помочь (?<=X) ( d . d ), я не знаю, поддерживается ли положительный внешний вид в sql-сервере или нет

4. @Larnu Это работает намного лучше PATINDEX 🙂

Ответ №1:

Если он всегда находится между последним X и последним G , вы могли бы использовать пару CHARINDEX «s, как вы пробовали. Я предпочитаю делать это в FROM и использовать APPLY , чтобы избежать повторения кода и «неприятного» длинного одиночного выражения:

 SELECT *,REVERSE(SUBSTRING(R.YourString,CI1.I 1,CI2.I-CI1.I-1))
FROM (VALUES('DOT LTB TOL SP BLM 3X(35X25.1GR)BWY BNL'))V(YourString)
     CROSS APPLY(VALUES(REVERSE(V.YourString)))R(YourString)
     CROSS APPLY(VALUES(NULLIF(CHARINDEX('G',R.YourString),0)))CI1(I)
     CROSS APPLY(VALUES(NULLIF(CHARINDEX('X',R.YourString,CI1.I),0)))CI2(I)
  

Кстати, это действительно длинное выражение будет следующим:

 SELECT V.Yourstring,
       REVERSE(SUBSTRING(REVERSE(V.YourString),NULLIF(CHARINDEX('G',REVERSE(V.YourString)),0) 1,NULLIF(CHARINDEX('X',REVERSE(V.YourString),NULLIF(CHARINDEX('G',REVERSE(V.YourString)),0)),0)-NULLIF(CHARINDEX('G',REVERSE(V.YourString)),0)-1))
FROM (VALUES('DOT LTB TOL SP BLM 3X(35X25.1GR)BWY BNL'))V(YourString)
  

Получайте удовольствие, пытаясь это прочитать. Следовательно, почему APPLY s. 🙃

Комментарии:

1. Требуется время, чтобы понять 😉 отлично работает, спасибо!

2. Добро пожаловать, @GabinLegrand . Если он отвечает на вопрос, пожалуйста, подумайте о том, чтобы пометить его как решение, чтобы будущие читатели знали, что это было полезно. Спасибо.