0

Assuming you have the string below, how would you recommend parsing it out into its various values? Each "record" ends with a break tag. The first value is the event name, the second between the parentheses is the account number, next is the ticket quantity and lastly is the total price paid.

Education Luncheon (501-2620) - 2 - $110<br>Womens Breakfast (512-2620) - 2 - $80<br>Friday Luncheon (502-26200) - 2 - 110<br>
3
  • 2
    If this is to be used in another application like .net, java, whatever, I suggest doing the parsing in the application code as opposed to sql. Commented Apr 20, 2015 at 22:51
  • Gonna be used in ColdFusion, was hoping to do in SQL but I'll dust off my CF skills and see if that will work. Commented Apr 20, 2015 at 22:59
  • You can also take a look at CLR Function and/or User-defined function Commented Apr 20, 2015 at 23:01

2 Answers 2

2

I want to so say a direct query with use of XML parsing and PARSENAME and REPLACE functions without using any UDF:

Suppose this string:

DECLARE @str VARCHAR(MAX)='Education Luncheon (501-2620) - 2 - $110<br>Womens Breakfast (512-2620) - 2 - $80<br>Friday Luncheon (502-26200) - 2 - 110<br>'

now just with converting that string to XML and parsing it inside a cte and finally using the mentioned string functions:

   ;WITH cte AS(   
      SELECT Value = tbl.fld.value('(./text())[1]', 'nvarchar(4000)')            
      FROM 
      ( 
        SELECT 
            v = CONVERT(XML, '<i>' 
                + REPLACE(@str, '<br>' , '</i><i>') 
                + '</i>')
      ) AS a 
      CROSS APPLY v.nodes('i') AS tbl(fld)
      WHERE tbl.fld.value('(./text())[1]', 'nvarchar(4000)') IS NOT NULL
    )
    SELECT PARSENAME(REPLACE(Value ,'(','.'),2) AS [Event],
           PARSENAME(REPLACE(REPLACE(Value ,'(','.') ,')','.'),2)AS AccNumber,
           PARSENAME(REPLACE(Value ,'-','.'),2) AS Qty ,
           PARSENAME(REPLACE(Value ,'-','.'),1) AS Price         
    FROM cte

We will get this Result:

|               Event | AccNumber | Qty | Price |
|---------------------|-----------|-----|-------|
| Education Luncheon  |  501-2620 |  2  |  $110 |
|   Womens Breakfast  |  512-2620 |  2  |   $80 |
|    Friday Luncheon  | 502-26200 |  2  |   110 |
Sign up to request clarification or add additional context in comments.

1 Comment

Had to make a couple tweaks, but otherwise this works pretty well with a reasonable amount of code.
1

First Create a Split function. then use the following query .

Split Function

CREATE FUNCTION dbo.Split
(
  @delimited nvarchar(max),
  @delimiter nvarchar(100)
) RETURNS @t TABLE
(
-- Id column can be commented out, not required for sql splitting string
  id int identity(1,1), -- I use this column for numbering splitted parts
  val nvarchar(max)
)
AS
BEGIN
  declare @xml xml
  set @xml = N'<root><r>' + replace(@delimited,@delimiter,'</r><r>') + '</r></root>'

  insert into @t(val)
  select
    r.value('.','varchar(max)') as item
  from @xml.nodes('//root/r') as records(r)

  RETURN
END
GO

Test Data & Query

DECLARE @String VARCHAR(1000) = 'Education Luncheon (501-2620) - 2 - $110<br>Womens Breakfast (512-2620) - 2 - $80<br>Friday Luncheon (502-26200) - 2 - 110<br>'


SELECT LEFT(val , CHARINDEX('(', Val) -1 ) AS EventName  
      ,REPLACE( REPLACE(
           SUBSTRING(Val , CHARINDEX('(', Val) , LEN(Val) -  CHARINDEX(')', Val))
             ,'(',''),')','') AS AccountNumber
      ,REPLACE(SUBSTRING(Val, 
                CHARINDEX(') -', Val) +2,  LEN(Val) - CHARINDEX(') -', Val) 
              - CHARINDEX('-', REVERSE(Val)))
              ,'-','') AS Quantity 
     ,PARSENAME(REPLACE(Val ,'-','.'),1) AS PricePaid         
FROM dbo.Split(@String, '<br>')
WHERE NULLIF(val ,'') IS NOT NULL

Result Set

╔═════════════════════╦═══════════════╦══════════╦═══════════╗
║      EventName      ║ AccountNumber ║ Quantity ║ PricePaid ║
╠═════════════════════╬═══════════════╬══════════╬═══════════╣
║ Education Luncheon  ║ 501-2620      ║       2  ║  $110     ║
║ Womens Breakfast    ║ 512-2620      ║       2  ║  $80      ║
║ Friday Luncheon     ║ 502-26200     ║       2  ║  110      ║
╚═════════════════════╩═══════════════╩══════════╩═══════════╝

1 Comment

I have changed the data around a little bit to see if it still works and unless data is way out of order it works :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.