Solved

How to return only part of a string field in sql query

Posted on 2010-09-10
14
555 Views
Last Modified: 2012-05-10
Hi Experts,

I want to extract a very small part of a large nvarchar field containing legacy data in order to update a new table.

From the information in this table I wish to get, amongst other fields which are straightforward,   a number that is present embedded in text in only some lines, eg:

Field [Legacy_data] contains 'a random amount of text ( 2.3)Kg another random amount of text'
I want to return only the 2.3 from withing the ()Kg and ONLY from those lines that contain '%)Kg%'. Can this be done easily?
0
Comment
Question by:alexking
  • 5
  • 5
  • 4
14 Comments
 
LVL 16

Expert Comment

by:vdr1620
Comment Utility
try the below SQL

EX:
SELECT SUBSTRING('a random amount of text ( 2.3)Kg another random amount of text',PATINDEX ('%(%','a random amount of text ( 2.3)Kg another random amount of text')+1,
                    PATINDEX ('%)%','a random amount of text ( 2.3)Kg another random amount of text')-PATINDEX ('%(%','a random amount of text ( 2.3)Kg another random amount of text')-1)

WHERE Clause


SELECT SUBSTRING(ColumnName,PATINDEX ('%(%',ColumnName)+1,

                    PATINDEX ('%)%',ColumnName)-PATINDEX ('%(%',ColumnName)-1)

WHERE ColumnName LIKE '%)Kg%'

Open in new window

0
 
LVL 16

Accepted Solution

by:
vdr1620 earned 250 total points
Comment Utility
small Correction add a FROM Clause to the SQL above
SELECT SUBSTRING(ColumnName,PATINDEX ('%(%',ColumnName)+1,

           PATINDEX ('%)%',ColumnName)-PATINDEX ('%(%',ColumnName)-1)

FROM tableName

WHERE ColumnName LIKE '%)Kg%'

Open in new window

0
 

Author Comment

by:alexking
Comment Utility
Thats almost perfect, only thing is if the text before the ()Kg contains "(" then I am getting a load of text returned - can I centre the extract on the ")Kg" part of text?

e.g. some amount of text  (Lab results pending - blah blah weight was ( 2.3)Kg and we expect an increase

is returning:

Lab results pending - blah blah weight was ( 2.3

All other lines are fine, only those with a "(" in the previous text are wrong.

0
 
LVL 92

Expert Comment

by:Patrick Matthews
Comment Utility
Try changing your pattern for PATINDEX to:

'%(%[0-9]%)Kg%'
0
 
LVL 92

Assisted Solution

by:Patrick Matthews
Patrick Matthews earned 250 total points
Comment Utility
This seems somewhat more robust:


SELECT LTRIM(RTRIM(SUBSTRING(SomeColumn, PATINDEX('%([ 0-9]%)Kg%', SomeColumn) + 1,
	CHARINDEX(')Kg', SomeColumn, PATINDEX('%([ 0-9]%)Kg%', SomeColumn)) - 
	PATINDEX('%([ 0-9]%)Kg%', SomeColumn) - 1)))
FROM SomeTable
WHERE SomeColumn LIKE '%([ 0-9]%)Kg%'

Open in new window

0
 

Author Comment

by:alexking
Comment Utility
This is really really close but is still returning text up to the first "(" in the string if more than 1 is present.
0
 
LVL 16

Expert Comment

by:vdr1620
Comment Utility
Patrick's SQL seems to work..

CREATE TABLE #T
(
ColumnName Nvarchar(max)
)

INSERT INTO #T Values ('(Lab results pending - blah blah weight was (2.3)Kg and we expect an increase ')

SELECT LTRIM(RTRIM(SUBSTRING(ColumnName, PATINDEX('%([ 0-9]%)Kg%', ColumnName) + 1,
      CHARINDEX(')Kg', ColumnName, PATINDEX('%([ 0-9]%)Kg%', ColumnName)) -
      PATINDEX('%([ 0-9]%)Kg%', ColumnName) - 1)))
FROM #T
WHERE ColumnName LIKE '%([ 0-9]%)Kg%'
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:alexking
Comment Utility
Yes, I tried it again and works perfectly - but if I insert this text into the table it doesn't work, is there anything in this text that would throw it out? If its just that the text is too random, I can go through and adjust manually.

Combo ( 30.08  Apply One Vial Every 1  Months To Skin Behind Nec   31-03-10  ?advise Next Time  *weight Entered As ( .95)kg.  Payment: Cash KG  81.8  2nd VA/Nar  Offer KG
0
 
LVL 92

Expert Comment

by:Patrick Matthews
Comment Utility
OK, try this:


SELECT LTRIM(RTRIM(SUBSTRING(SomeColumn, PATINDEX('%([ .0-9]%)Kg%', SomeColumn) + 1,
	CHARINDEX(')Kg', SomeColumn, PATINDEX('%([ .0-9]%)Kg%', SomeColumn)) - 
	PATINDEX('%([ .0-9]%)Kg%', SomeColumn) - 1)))
FROM SomeTable
WHERE SomeColumn LIKE '%([ .0-9]%)Kg%'

Open in new window

0
 
LVL 16

Expert Comment

by:vdr1620
Comment Utility
it is showing up  because the SQL above tests for condition Like ( followed by numbers.. and since there are two of those kind in the Value its picking the First match i.e., ( 30.08 and then calculating the difference of length between the 1st ( bracket and )  and that's the reason you see that result instead of .95

for your ref:
http://msdn.microsoft.com/en-us/library/ms188395.aspx
0
 
LVL 92

Expert Comment

by:Patrick Matthews
Comment Utility
I'm beginning to think that maybe you're better off using a .Net CLR function leveraging Regular Expressions.

Alas, I will not be able to help with that, as I am a .Net n00b.
0
 

Author Closing Comment

by:alexking
Comment Utility
Many thanks both, I had not come across these sql functions before and now will go and learn to use them properly!
The solution was close enough to get me the info I need, I hope splitting the points between you is OK?
0
 
LVL 92

Expert Comment

by:Patrick Matthews
Comment Utility
Glad to help, and no problem at all with the split :)
0
 
LVL 16

Expert Comment

by:vdr1620
Comment Utility
also.. check this.. i added some SQL to mathew's Script


SELECT CASE WHEN LEN(ColumnName) > 6 THEN LTRIM(RTRIM(SUBSTRING(ColumnName,CharINDEX('(',ColumnName)+1,6)))
            ELSE ColumnName END
FROM
(
SELECT LTRIM(RTRIM(SUBSTRING(ColumnName, PATINDEX('%([ 0-9]%)Kg%', ColumnName) + 1,
      CHARINDEX(')Kg', ColumnName, PATINDEX('%([ 0-9]%)Kg%', ColumnName)) -
      PATINDEX('%([ 0-9]%)Kg%', ColumnName) - 1))) as ColumnName
FROM #T
WHERE ColumnName LIKE '%([ 0-9]%)Kg%'
)derived
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Occasionally there is a need to clean table columns, especially if you have inherited legacy data. There are obviously many ways to accomplish that, including elaborate UPDATE queries with anywhere from one to numerous REPLACE functions (even within…
In this article we will get to know that how can we recover deleted data if it happens accidently. We really can recover deleted rows if we know the time when data is deleted by using the transaction log.
This video shows, step by step, how to configure Oracle Heterogeneous Services via the Generic Gateway Agent in order to make a connection from an Oracle session and access a remote SQL Server database table.
Viewers will learn how to use the INSERT statement to insert data into their tables. It will also introduce the NULL statement, to show them what happens when no value is giving for any given column.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now