开发者

Parsing Out Data in Varying Lengths to be used in a stored procedure to calculate a field

I have a database field with data like the examples below:

FEE 200 A 16 Y N NYFIRE 32.8 C M0008 Y N

INF 150 A 05 Y Y PFE 35 A 05 Y Y

NYFEE 200 A 16 Y N

I need to parse out all the values with an A before them, or any values that are preceded with an INF. If they are preceded with an INF I need to use those values to deduct them from a formula in SQL. If the values are not preceded with an INF, but are followed by an A I need to add those values in a formula in a stored procedure. IMPORTANT, what looks like spaces in the examples are CHAR(9) characters. There could be up to 9 series of numbers that have an A before them... the above examples only show 1 or 2. I can extract out the first one using a charindex, but don't know how to get the subsequent A's out. I can't get a patindex to work with a '%[' + CHAR(9) + 'INF' + CHAR(9) + ']%', but if I do patindex on just 'INF' then I can't get just the following value with the 'INF' as part of the string, I don't want the 'INF' part.

I开发者_开发知识库 don't know how to parse out the values in a stored procedure, or at all (I've tried a number of things as mentioned above), and have not been able to find anything except how to parse out data on specific patterns. There is not always the same number of spaces for the value preceding the A, it could be 2 or 3 characters.


This will parse out the values. In SQL 2005/2008 you can do

 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

You can either set up a loop (Which I don't recommend) or you can do the self joins to figure out what has an FEE and what has an INF and what values you want

 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

If you're using 2000 you'll need to set up a split function and loop through your data and call it

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

The split function is a modified for 2000 version of what is found here by 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜