Разбор данных в различных длинах для использования в хранимой процедуре для вычисления поля

У меня есть поле базы данных с данными, как примеры ниже:

FEE 200 A 16 YN NYFIRE 32,8 C M0008 YN
INF 150 A 05 YY PFE 35 A 05 YY
NYFEE 200 A 16 YN

Мне нужно разобрать все значения с A перед ними, или любые значения, которые начинаются с INF. Если им предшествует INF, мне нужно использовать эти значения, чтобы вычесть их из формулы в SQL. Если значения не предшествуют INF, но сопровождаются AI, необходимо добавить эти значения в формулу в хранимой процедуре. ВАЖНО, то, что в примерах выглядит как пробелы, это символы CHAR(9). Может быть до 9 серий чисел, перед которыми стоит буква A... в приведенных выше примерах показано только 1 или 2. Я могу извлечь первое с помощью charindex, но не знаю, как получить последующие буквы A, Я не могу заставить patindex работать с '%[' + CHAR(9) + 'INF' + CHAR(9) + ']%', но если я делаю patindex только с INF, то я не могу получить только следующее значение с INF в качестве части строки, я не хочу, чтобы часть INF.

Я не знаю, как анализировать значения в хранимой процедуре или вообще (я пробовал несколько вещей, как упомянуто выше), и не смог найти ничего, кроме как проанализировать данные по определенным шаблонам, Не всегда одинаковое количество пробелов для значения, предшествующего A, это может быть 2 или 3 символа.

1 ответ

Решение

Это будет анализировать значения. В SQL 2005/2008 вы можете сделать

 DECLARE @Test table 
(id int identity, field varchar(max))

INSERT INTO @Test  (field)
Values('FEE 200 A 16 Y N NYFIRE 32.8 C M0008 Y N')

INSERT INTO @Test  (field)
Values('INF 150 A 05 Y Y PFE 35 A 05 Y Y')

INSERT INTO @Test  (field)
Values('NYFEE 200 A 16 Y N')
Update @Test set Field = REPLACE(Field,' ', CHAR(9)) 


;with cte 
as
(

 SELECT 
       id, 
       cast(0 as bigint) ind, 
       cast('' as varchar(max)) foo, 
       1 anchor 
 FROM 
       @Test
 UNION ALL SELECT 
       n.id, CHARINDEX(Char(9),
       n.field, 
       cte.ind+1) ind , 
       SUBSTRING(field,cte.ind,CHARINDEX(Char(9),n.field, cte.ind+1) - cte.ind)  Foo, 
       0  anchor   
 FROM 
       @Test n
       INNER JOIN cte ON n.id = cte.id
 WHERE  
       CHARINDEX(Char(9),n.field, cte.ind+1) <> 0
 )

 select *
 from cte 
 where 
     anchor = 0


 order by id, ind

Вы можете либо настроить цикл (который я не рекомендую), либо вы можете сделать самостоятельные объединения, чтобы выяснить, что имеет FEE, а что INF и какие значения вы хотите

 select Fees.id, value.*

 from cte Fees
 INNER JOIN Cte a
 ON Fees.id = a.id and a.foo like '%A%'
  INNER JOIN Cte value
 ON a.id = value.id and a.ind < value.ind

 where 
 fees.anchor = 0
 and fees.foo like '%FEE'

 order by fees.id, fees.ind

Если вы используете 2000, вам нужно настроить функцию разделения, перебрать данные и вызвать их

SET QUOTED_IDENTIFIER ON
GO


CREATE FUNCTION [dbo].[Split]
(    
    @RowData VARCHAR(8000),
    @Delimeter NVARCHAR(2000)
)
RETURNS @RtnValue TABLE 
(
    ID INT IDENTITY(1,1),
    Data VARCHAR(8000)
) 
AS
BEGIN 
    DECLARE @Iterator INT
    SET @Iterator = 1

    DECLARE @FoundIndex INT
    SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)

    WHILE (@FoundIndex>0)
    BEGIN
        INSERT INTO @RtnValue (data)
        SELECT 
            Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))

        SET @RowData = SUBSTRING(@RowData,
                @FoundIndex + DATALENGTH(@Delimeter) / 2,
                LEN(@RowData))

        SET @Iterator = @Iterator + 1
        SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
    END

    INSERT INTO @RtnValue (Data)
    SELECT Data = LTRIM(RTRIM(@RowData))

        RETURN
    END
Go

Функция расщепления является модифицированной для 2000 версии того, что находится здесь у Itai Goldstein

 DECLARE @Test table 
(id int identity, fieldValue varchar(2000))

INSERT INTO @Test  (fieldValue)
Values('FEE 200 A 16 Y N NYFIRE 32.8 C M0008 Y N')

INSERT INTO @Test  (fieldValue)
Values('INF 150 A 05 Y Y PFE 35 A 05 Y Y')

INSERT INTO @Test  (fieldValue)
Values('NYFEE 200 A 16 Y N')
Update @Test set fieldValue = REPLACE(fieldValue,' ', CHAR(9)) 

DECLARE @fieldValue varchar(2000)
DECLARE @CurrentID int

    SELECT  @CurrentID = MIN(id)
    FROM
        @test



DECLARE @OUTPUT table 
 (id int , theOrder int, fieldValue varchar(2000))
DECLARE @rowData varchar(8000)

DECLARE @delimiter varchar(1)
SET @delimiter = char(9)

WHILE not @CurrentID IS NULL
BEGIN


    SELECT @rowData = FieldValue FROM @Test Where id = @currentID

    INSERT INTO @OUTPUT
    SELECT
         @currentID,
         s.ID,
         s.data
    FROM
        dbo.split(@rowdata, @delimiter) s


    SELECT  @CurrentID = MIN(id)
    FROM
        @test
    WHERE 
        id > @CurrentID



END

SELECT * FROM @OUTPUT
Другие вопросы по тегам