Parsing a String Sql

How to parse a string and create several columns from it?

SELECT substring(NameValue, 1, charindex('_', NameValue)-1) AS Names, 
substring(NameValue, charindex('_', NameValue)+1, LEN(NameValue)) AS Values
FROM Table

EDIT:
Something like this put in a function or stored procedure combined with a temp table should work for more than one line, depending on the line delimiter you should also remove CHAR(13) before you start:

DECLARE @helper varchar(512)
DECLARE @current varchar(512)
SET @helper = NAMEVALUE
WHILE CHARINDEX(CHAR(10), @helper) > 0 BEGIN
SET @current = SUBSTRING(@helper, 1, CHARINDEX(CHAR(10), @helper)-1)
SELECT SUBSTRING(@current, 1, CHARINDEX('_', @current)-1) AS Names,
SUBSTRING(@current, CHARINDEX('_', @current)+1, LEN(@current)) AS Names
SET @helper = SUBSTRING(@helper, CHARINDEX(CHAR(10), @helper)+1, LEN(@helper))
END
SELECT SUBSTRING(@helper, 1, CHARINDEX('_', @helper)-1) AS Names,
SUBSTRING(@helper, CHARINDEX('_', @helper)+1, LEN(@helper)) AS Names

How do I split a delimited string so I can access individual items?

You may find the solution in SQL User Defined Function to Parse a Delimited String helpful (from The Code Project).

You can use this simple logic:

Declare @products varchar(200) = '1|20|3|343|44|6|8765'
Declare @individual varchar(20) = null

WHILE LEN(@products) > 0
BEGIN
IF PATINDEX('%|%', @products) > 0
BEGIN
SET @individual = SUBSTRING(@products,
0,
PATINDEX('%|%', @products))
SELECT @individual

SET @products = SUBSTRING(@products,
LEN(@individual + '|') + 1,
LEN(@products))
END
ELSE
BEGIN
SET @individual = @products
SET @products = NULL
SELECT @individual
END
END

How to parse a string with multiple underscores and dashes

Another option is a little XML

Not clear if you want a comma delimited string or separate columns

Example

Declare @YourTable Table ([ID] varchar(50),[SomeCol] varchar(150))
Insert Into @YourTable Values
(1,'Automation_LOY_Loyalty_PC_CampaignName3-Abandoners-Email1_NoPromo_USA')
,(2,'20200601_LOY_Functional_PC_CampaignName1_NoPromo_CAN')

Select A.ID
,B.Pos1
,B.Pos2
,B.Pos3
,B.Pos4
,Pos5a = xmlData.value('/x[1]','varchar(max)')
,Pos5b = xmlData.value('/x[2]','varchar(max)')
,Pos5c = xmlData.value('/x[3]','varchar(max)')
,B.Pos6
,B.Pos7
From @YourTable A
Cross Apply (
Select Pos1 = xDim.value('/x[1]','varchar(max)')
,Pos2 = xDim.value('/x[2]','varchar(max)')
,Pos3 = xDim.value('/x[3]','varchar(max)')
,Pos4 = xDim.value('/x[4]','varchar(max)')
,Pos5 = xDim.value('/x[5]','varchar(max)')
,Pos6 = xDim.value('/x[6]','varchar(max)')
,Pos7 = xDim.value('/x[7]','varchar(max)')
From ( values (cast('<x>' + replace((Select replace(SomeCol,'_','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml))) A(xDim)
) B
Cross Apply ( values (cast('<x>' + replace((Select replace(Pos5,'-','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) ) ) C(xmlData)

Returns

Sample Image

Parse from string specific values in SQL Server

You should use substring

SELECT SUBSTRING('w3resource',4,3);

will out put eso 4,3 means start from 4th position till next 3 characters

so in your case it will be

SELECT SUBSTRING(column_name,67,4);

This is all about MYSQL but MS SQL has the same function

SUBSTRING( string, start_position, length )

Please check this link
http://social.technet.microsoft.com/wiki/contents/articles/17948.t-sql-right-left-substring-and-charindex-functions.aspx

Parse string as JSON with Snowflake SQL

Replace only one occurrence with regexp_replace():

with data as (
select '---\nfield_one: 1\nfield_two: 20\nfield_three: 4\nid: 1234\nanother_id: 5678\nsome_text: Hey you\na_date: 2022-11-29\nutc: this_utc\nanother_date: 2022-11-30\nutc: another_utc' o
)

select parse_json(last2)
from (
select o,
replace(o, '---\n', '{"') || '"}' as first,
replace(first, '\n', '","') as second_,
replace(second_, ': ', '":"') as third,
replace(third, ' ', '') as fourth,
replace(fourth, ' ', '') as last,
regexp_replace(last, '"utc"', '"utc2"', 1, 2) last2
from data
)
;

Sample Image

Parsing a string SQL

declare @s varchar(max) = 'I=940;A=29.5;D=20090901|I=941;A=62.54;D=20090910|I=942;A=58.99;D=20091005|I=954;A=93.45;D=20091201|I=944;A=96.76;D=20091101|I=946;A=52.5;D=20091101|I=943;A=28.32;D=20091101|I=945;A=52.5;D=20091101|I=955;A=79.81;D=20091201|I=950;A=25.2;D=20091124|I=948;A=31.86;D=20091110|I=949;A=28.32;D=20091120|I=947;A=25.2;D=20091109|I=951;A=242.54;D=20091124|I=952;A=28.32;D=20091129|I=956;A=38.94;D=20091210|I=957;A=107.39;D=20091215|I=958;A=32.55;D=20091228|I=959;A=27.3;D=20091228|I=960;A=24.79;D=20091230|I=1117;A=28.32;D=20100131|I=1115;A=272.58;D=20100131|I=1116;A=159.6;D=20100209'
declare @xml xml

select @xml = '<item><value>'+replace(replace(@s, ';','</value><value>'), '|','</value></item><item><value>')+'</value></item>'

select N.value('substring(value[1],3)', 'int') as Invoice,
N.value('substring(value[2],3)', 'money') as Amount,
N.value('substring(value[3],3)', 'date') as [Date]
from @xml.nodes('item') as T(N)

Result:

Invoice     Amount                Date
----------- --------------------- ----------
940 29,50 2009-09-01
941 62,54 2009-09-10
942 58,99 2009-10-05
954 93,45 2009-12-01
944 96,76 2009-11-01
946 52,50 2009-11-01
943 28,32 2009-11-01
945 52,50 2009-11-01
955 79,81 2009-12-01
950 25,20 2009-11-24
948 31,86 2009-11-10
949 28,32 2009-11-20
947 25,20 2009-11-09
951 242,54 2009-11-24
952 28,32 2009-11-29
956 38,94 2009-12-10
957 107,39 2009-12-15
958 32,55 2009-12-28
959 27,30 2009-12-28
960 24,79 2009-12-30
1117 28,32 2010-01-31
1115 272,58 2010-01-31
1116 159,60 2010-02-09

For SQL Server 2005 you need to use datetime instead of date

select N.value('substring(value[1],3)', 'int') as Invoice,
N.value('substring(value[2],3)', 'money') as Amount,
N.value('substring(value[3],3)', 'datetime') as [Date]
from @xml.nodes('item') as T(N)

To read from a table you need to do it like this.

declare @s varchar(max) = 'I=940;A=29.5;D=20090901|I=941;A=62.54;D=20090910|I=942;A=58.99;D=20091005|I=954;A=93.45;D=20091201|I=944;A=96.76;D=20091101|I=946;A=52.5;D=20091101|I=943;A=28.32;D=20091101|I=945;A=52.5;D=20091101|I=955;A=79.81;D=20091201|I=950;A=25.2;D=20091124|I=948;A=31.86;D=20091110|I=949;A=28.32;D=20091120|I=947;A=25.2;D=20091109|I=951;A=242.54;D=20091124|I=952;A=28.32;D=20091129|I=956;A=38.94;D=20091210|I=957;A=107.39;D=20091215|I=958;A=32.55;D=20091228|I=959;A=27.3;D=20091228|I=960;A=24.79;D=20091230|I=1117;A=28.32;D=20100131|I=1115;A=272.58;D=20100131|I=1116;A=159.6;D=20100209'

declare @YourTable table(ID int, s varchar(max))
insert into @YourTable values
(1, @s),
(2, @s)

select Y.ID,
T.N.value('substring(value[1],3)', 'int') as Invoice,
T.N.value('substring(value[2],3)', 'money') as Amount,
T.N.value('substring(value[3],3)', 'date') as [Date]
from @YourTable as Y
cross apply (select cast('<item><value>'+replace(replace(Y.s, ';','</value><value>'), '|','</value></item><item><value>')+'</value></item>' as xml)) as X(XMLCol)
cross apply X.XMLCol.nodes('item') as T(N)

Parsing a string in postgresql

We can use REGEXP_REPLACE here:

SELECT col, REGEXP_REPLACE(col, '.*\[\w+ UID=(\d+)\].*$', '\1') AS uid
FROM yourTable;

Demo

Edit:

In case a given value might not match the above pattern, in which case you would want to return the entire original value, we can use a CASE expression:

SELECT col,
CASE WHEN col LIKE '%[%UID=%]%'
THEN REGEXP_REPLACE(col, '.*\[\w+ UID=(\d+)\].*$', '\1')
ELSE col END AS uid
FROM yourTable;

How to parse SQL Server String in hour, min and second

You can also create a function to perform the conversion with basic text manipulation:

CREATE FUNCTION dbo.f_GetTime(@TimeInput VARCHAR(50)) RETURNS TIME
AS BEGIN
SET @TimeInput = REPLACE(REPLACE(@TimeInput, 'PT', ''), 'S', '')
IF CHARINDEX('H', @TimeInput) = 0 -- Add missing H
SET @TimeInput = '0H' + @TimeInput
IF CHARINDEX('M', @TimeInput) = 0 -- Add missing M
SET @TimeInput = REPLACE(@TimeInput, 'H', 'H0M')
RETURN CONVERT(TIME, REPLACE(REPLACE(@TimeInput, 'H', ':'), 'M', ':'))
END
GO

Then you can use it with just scalar queries:

SELECT dbo.f_GetTime('PT1H22M59.551S') AS TimeValue

Or you can use it with tables:

DECLARE @Input TABLE (TimeInput VARCHAR(20))
INSERT @Input VALUES ('PT1H22M59.551S'), ('PT0S'), ('PT6H4M29.212S'), ('PT0S'),
('PT2M55.126S'), ('PT54M4.12S'), ('PT3H6M5.74S'), ('PT16H27M52.069S')
SELECT TimeInput, dbo.f_GetTime(TimeInput) AS TimeValue FROM @Input

This would return:

TimeInput            TimeValue
-------------------- ----------------
PT1H22M59.551S 01:22:59.5510000
PT0S 00:00:00.0000000
PT6H4M29.212S 06:04:29.2120000
PT0S 00:00:00.0000000
PT2M55.126S 00:02:55.1260000
PT54M4.12S 00:54:04.1200000
PT3H6M5.74S 03:06:05.7400000
PT16H27M52.069S 16:27:52.0690000


Related Topics



Leave a reply



Submit