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 NI 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
精彩评论