Extracting substring between two characters (commas) - sql

I need to extract codes from a string separated by commas.
I have figured out how to extract the first code but i'm struggling trying to figure out how to extract subsequent codes.
Example string:
~R10.4,T85.8,Y83.8,I10X,I25.9,E10.9,Z95.5,Z93.2,Z88.0
Query:
select code_string, substring(code_string, 0, charindex(',',code_string)) as first
FROM TABLE
Returns:
~R10.4
I now need to extract subsequent codes
~R10.4
T85.8
Y83.8
I10X
etc.
any help would be greatly appreciated
I would prefer not to have to create a function if possible

I guess you're using SQL server if so you can use
SELECT value FROM
STRING_SPLIT('~R10.4,T85.8,Y83.8,I10X,I25.9,E10.9,Z95.5,Z93.2,Z88.0', ',');

thought I'd share my solution
;WITH Split_Field (CODE_STRING, xmlname)
AS
(
SELECT
CODE_STRING,
CONVERT(XML,'<Names><name>'
+ REPLACE(CODE_STRING,',', '</name><name>') + '</name></Names>') AS xmlname
FROM
(
Select cast('~I20.9,I10X,E78.0,H81.0,K90.0,M81.9,M19.9,Z86.7' as nvarchar(MAX))
/*replace with your code field*/ as CODE_STRING
--from table
) as A
)
SELECT
CODE_STRING,
xmlname.value('/Names[1]/name[1]','varchar(100)') AS Col1,
xmlname.value('/Names[1]/name[2]','varchar(100)') AS Col2,
xmlname.value('/Names[1]/name[3]','varchar(100)') AS Col3,
xmlname.value('/Names[1]/name[4]','varchar(100)') AS col4,
xmlname.value('/Names[1]/name[5]','varchar(100)') AS col5
FROM Split_Field

Related

SQL: select the last values before a space in a string

I have a set of strings like this:
CAP BCP0018 36
MFP ACZZ1BD 265
LZP FEI-12 3
I need to extract only the last values from the right and before the space, like:
36
265
3
how will the select statement look like? I tried using the below statement, but it did not work.
select CHARINDEX(myField, ' ', -1)
FROM myTable;
Perhaps the simplest method in SQL Server is:
select t.*, v.value
from t cross apply
(select top (1) value
from string_split(t.col, ' ')
where t.col like concat('% ', val)
) v;
This is perhaps not the most performant method. You probably would use:
select right(t.col, charindex(' ', reverse(t.col)) - 1)
Note: If there are no spaces, then to prevent an error:
select right(t.col, charindex(' ', reverse(t.col) + ' ') - 1)
Since you have mentioned CHARINDEX() in question, I am assuming you are using SQL Server.
Try below
declare #table table(col varchar(100))
insert into #table values('CAP BCP0018 36')
insert into #table values('MFP ACZZ1BD 265')
insert into #table values('LZP FE-12 3')
SELECT REVERSE(LEFT(REVERSE(col),CHARINDEX(' ',REVERSE(col)) - 1)) FROM #table
Functions used
CHARINDEX ( expressionToFind , expressionToSearch ) : returns position of FIRST occurence of an expression inside another expression.
LEFT ( character_expression , integer_expression ) : Returns the left part of a character string with the specified number of characters.
REVERSE ( string_expression ) : Returns the reverse order of a string value

Dynamic Comma Seperated string into different column

May someone please help me for this strange scenario. i have a data as given below.
DECLARE #TABLE TABLE
(
ID INT,
PHONE001 VARCHAR(500)
)
INSERT TEST
SELECT 1,'01323840261,01323844711' UNION ALL
SELECT 2,'' UNION ALL
SELECT 3,',01476862000' UNION ALL
SELECT 4,'01233625418,1223822583,125985' UNION ALL
SELECT 5,'2089840022,9.99021E+13'
and i am trying to put in seperate column for each comma value. the max number of column depends on the largest comma seperated string.
Expected Output
1|01323840261|01323844711|''
2|''|''|''
3|01476862000|''|''|
4|01233625418|1223822583|125985|
5|2089840022|9.99021E+13|''|
try
select id,T.c.value('t[1]','varchar(50)') as col1,
T.c.value('t[2]','varchar(50)') as col2 ,
T.c.value('t[3]','varchar(50)') as col3 from
(select id,cast ('<t>'+ replace(PHONE001,',','</t><t>') +'</t>'
as xml) x
from #TABLE) a cross apply x.nodes('.') t(c)

how to replace a comma with single quote comma in SQLIN clause

Hi all I have a an where clause like below
select * from table1
where colum1 IN (?parameter)
when I pass the values to the parameter they show up like below
('1,2,3') but to execute the query I need to change the values as ('1','2','3')
is there a way to replace the commas with single quotes comma in IN clause directly?
There is one hack to do what you want, using like:
select *
from table1
where ',' || column1 || ',' like '%,' || (?parameter) || ',%';
This functions, but it will not make use of an index on column1. You should think about other solutions, such as:
Parsing the string into a table variable.
Using in with a fixed number of parameters.
Storing the values in a table.
There may be other Oracle-specific solutions as well.
Use MS SQL, you can convert it into table value and using join for your condition, I am not familiar oracle but you can find same way to do it.
DECLARE #IDs varchar(max) ='1,2,3';
;WITH Cte AS
(
SELECT
CAST('<ID>' + REPLACE( #IDs, ',' , '</ID><ID>') + '</ID>' AS XML) AS IDs
)
SELECT '''' + Split.a.value('.', 'VARCHAR(100)') +'''' AS ID FROM Cte
CROSS APPLY Cte.IDs.nodes('/ID') Split(a)
You can achieve it using with clause. Logic here is to convert each comma separated value into different row.
with temp_tab as (
select replace(regexp_substr(parameter, '[^,]+',1, level),'''','') as str
from dual
connect by level<= length(regexp_replace(parameter, '[^,]+'))+1 )
select * from table1 where column1 in (select str from temp_tab);

case statement to delete extra spaces only when there is some

I replace all blanks with # using this
SELECT *, REPLACE(NAME,' ','#') AS NAME2
which results miss#test#blogs############## (different number of #s dependent on length of name!
I then delete all # signs after the name using this
select *, substring(Name2,0,charindex('##',Name2)) as name3
which then gives my desired results of, for example MISS#test#blogs
However some wheren't giving this result, they are null. This is because annoyingly some rows in the sheet I have read in dont have the spaces after the name.
is there a case statement i can use so it only deletes # signs after the name if they are there in the first place?
Thanks
The function rtrim can be used to remove trailing spaces. For example:
select replace(rtrim('miss test blogs '),' ','#')
-->
'miss#test#blogs'
Example at SQL Fiddle.
try this:
Declare #t table (name varchar(100),title varchar(100),forename varchar(100))
insert into #t
values('a b c','dasdh dsalkdk asdhl','asd dfg sd')
SELECT REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(name)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS Name,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(title)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS title,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(forename)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS forename
FROM #t WHERE
(CHARINDEX(' ',NAME) > 0 or CHARINDEX(' ',title) > 0 or CHARINDEX(' ',forename) > 0)
SQL Fiddle Demo
select name2, left(name2,len(name2)+1-patindex('%[^#]%',reverse(name2)+'.'))
from (
SELECT *, REPLACE(NAME,' ','#') AS NAME2
from t
) x;
Check this SQL Fiddle
For posterity, sample table:
create table t (name varchar(100));
insert t select 'name#name#ne###'
union all select '#name#name'
union all select 'name name hi '
union all select 'joe public'
union all select ''
union all select 'joe'
union all select 'joe '
union all select null
union all select ' leading spaces'
union all select ' leading trailing ';
Don't quite understand the question, but if the problem is there is not spaces after some names, can't you do this first:
SELECT *, REPLACE(NAME+' ',' ','#') AS NAME2
i.e., add a space to all names right off the bat?
I had this same problem some days ago.
Well actually, there's a quickly way to subtract the spaces from both the begin and end inside strings. In SQL Server, you can use the RTRIM and LTRIM for this. The first one supresses spaces from right side and the second supresses from left. But, if in your scenario also may exists more than one space in the middle of the string I sugest you take a look on this post on SQL Server Central: http://www.sqlservercentral.com/articles/T-SQL/68378/
There the script's author explain, in details, a good solution for this situation.

Extracting from text using tsql

I have the following string format in a Sql table column
[CID]: 267 [MID]: 319A [Name]: RJR
How can I extract only the value of MID which is 319A in select query so I can use the MID in a join.
In other words I need to extract the MID value from this text field to use it in a join. I copy/pasted the value and it looks like there are /n (new line) characters after each value.
Thanks in advance
you may try this one.
declare
#t varchar(100)
set #t = '[CID]: 267 [MID]: 319A [Name]: RJR';
select ltrim(rtrim(substring(#t,charindex('[MID]:',#t)+6,(charindex('[NAME]',#t))-(charindex('[MID]:',#t)+6))))
---------------------------------------------------------
319A
ltrim and rtrim will trim your 319A value.
you can try without them at start if you like.
Cheers
http://www.simple-talk.com/sql/t-sql-programming/tsql-regular-expression-workbench/
to add regex support to sql server
Rubular Regex to get you started:
\[MID\]: (.*) \[Name]:
Not clean at ALL, but if you need it in SQL, here you go:
Use
SUBSTRING ( value_expression , start_expression , length_expression )
and
LOCATE( string1, string2 [, start] )
together:
SUBSTRING(INPUT,
((SELECT LOCATE( 'MID]: ', INPUT ))+6),
((SELECT LOCATE( '[Name]', INPUT )) - ((SELECT LOCATE( 'MID]: ', INPUT ))+6))
depending where is taking place? If it is in a batch process, I would export those fields with an ID, write a perl one liner that extracts them, and then load them back to the db. it would be so much faster than using these functions.
if it is screen event, then I suggest breaking them into 3 columns instead, itll actully save you space.
Don't really think you need all these trimming and substring-ing functions.
USE tempdb;
GO
CREATE TABLE #t1
(
a INT,
b VARCHAR(64)
);
INSERT #t1 SELECT 1, '[CID]: 267 [MID]: 319A [Name]: RJR'
UNION ALL SELECT 2, '[CID]: 26232 [MID]: 229dd5A [Name]: RJ'
UNION ALL SELECT 3, 'Garbage that will not match';
CREATE TABLE #t2
(
c INT,
d VARCHAR(32)
);
INSERT #t2 SELECT 4, '319A'
UNION ALL SELECT 5, '229dd5A'
UNION ALL SELECT 6, 'NO MATCH';
SELECT t1.a, t1.b, t2.c, t2.d
FROM #t1 AS t1
INNER JOIN #t2 AS t2
ON t1.b LIKE '%`[MID`]: ' + t2.d + ' %' ESCAPE '`'
GO
DROP TABLE #t1, #t2;
If you have no idea how many spaces might be between [MID]: and the start of your value, or the end of your value and the start of the next [, and assuming there are no spaces in the values you want to match, you could use:
ON REPLACE(t1.b, ' ', '') LIKE '%`[MID`]:' + t2.d + '`[%' ESCAPE '`'