Find Substring in SQL - sql

I have to find substring as follows.
Data as below
aaaa.bbb.ccc.dddd.eee.fff.ggg
qq.eeddde.rrr.t.hh.jj.jj.hh.hh
ee.r.t.y.u.i.ii.
I want output as-
bbb
eeeddde
r
challenge I am facing is all have (.) as separator so sub-string is tough to work.
SELECT SUBSTRING(string,CHARINDEX('.',string)+1,
(((LEN(string))-CHARINDEX('.', REVERSE(string)))-CHARINDEX('.',string))) AS Result
FROM [table]
bbb
eeeddde
r
looking substring between first and secound (.)
then it might be between second and third (.)

Here is one method:
select left(v.str1, charindex('.', v.str1 + '.') - 1)
from t cross apply
(values (stuff(t.string, 1, charindex('.', t.string + '.'), '')
) v(str1)

I assume (CHARINDEX) this is ms sql server.
CROSS APPLY is handy for intermediate calculations.
SELECT t.pos, t1.pos,
SUBSTRING(string, t.pos + 1, t1.pos - t.pos -1) AS Result
FROM [table]
CROSS APPLY ( VALUES(CHARINDEX('.',string)) ) t(pos)
CROSS APPLY ( VALUES(CHARINDEX('.',string, t.pos+1))) t1(pos)

Just another option is to use a little XML
Example
Declare #YourTable table (ID int,SomeColumn varchar(max))
Insert Into #YourTable values
(1,'aaaa.bbb.ccc.dddd.eee.fff.ggg')
,(2,'qq.eeddde.rrr.t.hh.jj.jj.hh.hh')
,(3,'ee.r.t.y.u.i.ii.')
Select ID
,SomeValue = convert(xml,'<x>' + replace(SomeColumn,'.','</x><x>')+'</x>').value('/x[2]','varchar(100)')
From #YourTable
Returns
ID SomeValue
1 bbb
2 eeddde
3 r

You can use left(), replace() and charindex() functions together :
select replace(
replace(
left(str,charindex('.',str,charindex('.',str)+1)),
left(str,charindex('.',str)),
''
),
'.'
,''
) as "Output"
from t;
Demo

Related

SQL - Split Concatenated String into Columns after ;

I really need help with SQL. I have a database where you can find values like: abc;defg;hi and this is in just 1 column. So I wanna create 2 more colums which inserts the splited values.
For example:
Before:
Value01: abc;defg;hi
After:
Value01: abc,
Value02: defg,
Value03: hi
--Another Example would be this:--
Before:
Value01: abcd;efg;
After:
Value01: abcd,
Value02: efg,
Value03: null
So always 3 new values were created. I hope you understand my question!
Greetings
You can use string_split():
select nullif(s.value, '')
from string_split(#value, ';') s
Use WITH
WITH CTE
AS
(
SELECT [xml_val] = CAST('<t>' + REPLACE(SomeValue,';','</t><t>') + '</t>' AS XML)
FROM #yourTable
)
SELECT [SomeValue] = col.value('.','VARCHAR(100)')
FROM CTE
CROSS APPLY [xml_val].nodes('/t') CA(col)
Here is a solution that should be fairly performant:
--==== Sample Data
Declare #testData Table (Value01 varchar(255));
Insert Into #testData (Value01)
Values ('abc;defg;hi'), ('abcd;efg;');
--==== Solution using sample data from above
Select *
, Value01 = substring(td.Value01, 1, p1.pos - 2)
, Value02 = substring(td.Value01, p1.pos, p2.pos - p1.pos - 1)
, Value03 = substring(td.Value01, p2.pos, p3.pos - p2.pos - 1)
From #testData td
Cross Apply (Values (concat(td.Value01, ';;;'))) As v(Value01) --Make sure we have delimiters
Cross Apply (Values (charindex(';', v.Value01, 1) + 1)) As p1(pos)
Cross Apply (Values (charindex(';', v.Value01, p1.pos) + 1)) As p2(pos)
Cross Apply (Values (charindex(';', v.Value01, p2.pos) + 1)) As p3(pos) --End of string/element
You could also create a function that parses out the elements and then just call the function using cross apply.

SQL Server : how to remove leading/trailing non-alphanumeric characters from string?

I am using SQL Server 2008, and try to sanitize a list of urls.
Some existing examples of texts:
www.google.com
'www.google.com'
/www.google.com
www.google.com/
Ideally I can strip any leading/trailing non-alphanumeric characters so the four would give out the same output as
www.google.com
Well, if you know they are only at the beginning and end, you can do:
with t as (
select *
from (values ('www.google.com'), ('''www.google.com'''), ('/www.google.com')) v(text)
)
select t.text, v2.text2
from t cross apply
(values (stuff(t.text, 1, patindex('%[a-zA-Z0-9]%', t.text) - 1, ''))
) v(text1) cross apply
(values (case when v.text1 like '%[^a-zA-Z0-9]'
then stuff(v.text1, len(text) + 1 - patindex('%[a-zA-Z0-9]%', reverse(v.text1)), len(v.text1), '')
else v.text1
end)
) v2(text2);
Here is a db<>fiddle.
Why not just use replace() ?:
SELECT REPLACE(REPLACE(col, '''', ''), '/', '')
You should be able to use Substring. Calculating length can be tricky:
DECLARE #temp TABLE (val varchar(100))
INSERT INTO #temp VALUES
('www.google.com'),('''www.google.com'''),('/www.google.com'),('www.google.com/'),('[www.google.com];')
SELECT SUBSTRING(val
,PATINDEX('%[a-zA-Z0-9]%', val) --start at position
,LEN(val) + 2 - PATINDEX('%[a-zA-Z0-9]%', val)
- PATINDEX('%[a-zA-Z0-9]%', REVERSE(val)) --length of substring
) AS [Result]
FROM #temp
Produces output:
Result
--------------
www.google.com
www.google.com
www.google.com
www.google.com
www.google.com

Semicolon seperated value to other column in sql server

i have a table with a column have value seperated by semi colon.
the concern is value in the column are not fixed. it starts from 1 and end upto 80 semicolon sepaeration.
i am trying to put each individual value to seperate column
SQL SERVER 2008 code
DECLARE #Table TABLE(
Val VARCHAR(50)
)
INSERT INTO #Table (Val) SELECT '2Xcalcium; kidney' union all SELECT '3XMagnessium; liver' union all SELECT '2-ECG;3XSODIUM;DIALYSIS'
SELECT *,
CAST(LEFT(Val,CHARINDEX(';',Val)-1) AS VARCHAR) FirstValue,
CAST(RIGHT(Val,LEN(Val) - CHARINDEX(';',Val)) AS VARCHAR) SecondValue
FROM #Table
I tried the above code but this is limited to 2 semicolon only. please share your expertise.
Try it like this:
DECLARE #Table TABLE(
Val VARCHAR(50)
)
INSERT INTO #Table (Val) SELECT '2Xcalcium; kidney' union all SELECT '3XMagnessium; liver' union all SELECT '2-ECG;3XSODIUM;DIALYSIS';
;WITH Splitted AS
(
SELECT *
,CAST('<x>' + REPLACE(Val,';','</x><x>') + '</x>' AS XML) ValuesAsXML
FROM #Table
)
SELECT *
,ValuesAsXML.value('x[1]','varchar(max)') AS FirstCol
,ValuesAsXML.value('x[2]','varchar(max)') AS SecondCol
,ValuesAsXML.value('x[3]','varchar(max)') AS ThirdCol
,ValuesAsXML.value('x[4]','varchar(max)') AS FourthCol
,ValuesAsXML.value('x[5]','varchar(max)') AS FifthCol
FROM Splitted
The result
Val FirstCol SecondCol ThirdCol FourthCol FifthCol
2Xcalcium; kidney 2Xcalcium kidney NULL NULL NULL
3XMagnessium; liver 3XMagnessium liver NULL NULL NULL
2-ECG;3XSODIUM;DIALYSIS 2-ECG 3XSODIUM DIALYSIS NULL NULL
Most of the link provided extract the element into rows.
If you prefer to use your existing logic and extract the individual element into separate column, you can use multiple cascaded CROSS APPLY.
SELECT t.Val,
v1.V as V1,
v2.V as V2,
v3.V as V3
FROM #Table t
cross apply
(
select V = LEFT(t.Val, CHARINDEX(';', t.Val + ';') - 1),
Val = STUFF(t.Val, 1, CHARINDEX(';', t.Val + ';'), '')
) v1
cross apply
(
select V = LEFT(v1.Val, CHARINDEX(';', v1.Val + ';') - 1),
Val = STUFF(v1.Val, 1, CHARINDEX(';', v1.Val + ';'), '')
) v2
cross apply
(
select V = LEFT(v2.Val, CHARINDEX(';', v2.Val + ';') - 1),
Val = STUFF(v2.Val, 1, CHARINDEX(';', v2.Val + ';'), '')
) v3
From your question ,it seems that you have data in below format..This can be done easily with numbers table..
declare #string varchar(max)
set #string='s,t,a,c,k'
select substring(','+#string+',',n+1,charindex(',',','+#string+',',n+1)-n-1)
from
numbers
where n<=len(#string)
and substring(','+#string+',',n,1)=','
Output:
s
t
a
c
k
Few more Gems:
https://dba.stackexchange.com/questions/11506/why-are-numbers-tables-invaluable
http://sqlperformance.com/2012/07/t-sql-queries/split-strings

Selecting between quotes (") in SQL Server 2012

I have a table holding IDs in one column and a string in the second column like below.
COLUMN01 COLUMN02
----------------------------------------------------------------------------------
1 abc"11444,12,13"efg"14,15"hij"16,17,18,19"opqr
2 ahsdhg"21,22,23"ghshds"24,25"fgh"26,27,28,28"shgshsg
3 xvd"3142,32,33"hty"34,35"okli"36,37,38,39"adfd
Now I want to have the following result
COLUMN01 COLUMN02
-----------------------------------------------------------
1 11444,12,13,14,15,16,17,18,19
2 21,22,23,24,25,26,27,28,28
3 3142,32,33,34,35,36,37,38,39
How can I do that?
Thanks so much
Here is one way (maybe not the best, but it seems to work). I am NOT a SQL guru...
First, create this SQL Function. It came from: Extract numbers from a text in SQL Server
create function [dbo].[GetNumbersFromText](#String varchar(2000))
returns table as return
(
with C as
(
select cast(substring(S.Value, S1.Pos, S2.L) as int) as Number,
stuff(s.Value, 1, S1.Pos + S2.L, '') as Value
from (select #String+' ') as S(Value)
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
union all
select cast(substring(S.Value, S1.Pos, S2.L) as int),
stuff(S.Value, 1, S1.Pos + S2.L, '')
from C as S
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
where patindex('%[0-9]%', S.Value) > 0
)
select Number
from C
)
Then, you can do something like this to get the results you were asking for. Note that I broke the query up into 3 parts for clarity. And, obviously, you don't need to declare the table variable and insert data into it.
DECLARE #tbl
TABLE (
COLUMN01 int,
COLUMN02 varchar(max)
)
INSERT INTO #tbl VALUES (1, 'abc"11444,12,13"efg"14,15"hij"16,17,18,19"opqr')
INSERT INTO #tbl VALUES (2, 'ahsdhg"21,22,23"ghshds"24,25"fgh"26,27,28,28"shgshsg')
INSERT INTO #tbl VALUES (3, 'xvd"3142,32,33"hty"34,35"okli"36,37,38,39"adfd')
SELECT COLUMN01, SUBSTRING(COLUMN02, 2, LEN(COLUMN02) - 1) as COLUMN02 FROM
(
SELECT COLUMN01, REPLACE(COLUMN02, ' ', '') as COLUMN02 FROM
(
SELECT COLUMN01, (select ',' + number as 'data()' from dbo.GetNumbersFromText(Column02) for xml path('')) as COLUMN02 FROM #tbl
) t
) tt
GO
output:
COLUMN01 COLUMN02
1 11444,12,13,14,15,16,17,18,19
2 21,22,23,24,25,26,27,28,28
3 3142,32,33,34,35,36,37,38,39
I know you want to do it using SQL. But ones I had nearly the same problem and getting this data to a string using a php or another language, than parsing is a way to do it. For example, you can use this kind of code after receiving the data into a string.
function clean($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
$string = preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
return preg_replace('/-+/', '-', $string); // Replaces multiple hyphens with single one.
}
For more information you might want to look at this post that I retrieved the function: Remove all special characters from a string
As I said this is an easy way to do it, I hope this could help.

Extract one value from a column containing multiple delimited values

How can I get the value from the sixth field in the following column? I am trying to get the 333 field:
ORGPATHTXT
2123/2322/12323/111/222/333/3822
I believe I have to use select substring, but am unsure how to format the query
Assuming SQL Server
The easiest way I can think of is create a Split function that splits based on '/' and you extract the sixth item like below
declare #text varchar(50) = '2123/2322/12323/111/222/333/3822'
select txt_value from fn_ParseText2Table(#text, '/') t where t.Position = 6
I used the function in this url. See it worked at SQLFiddle
Try this - for a string variable or wrap into a function to use with a select query (Sql-Demo)
Declare #s varchar(50)='2123/2322/12323/111/222/333/3822'
Select #s = right(#s,len(#s)- case charindex('/',#s,1) when 0 then len(#s)
else charindex('/',#s,1) end)
From ( values (1),(2),(3),(4),(5)) As t(num)
Select case when charindex('/',#s,1)>0 then left(#s,charindex('/',#s,1)-1)
else #s end
--Results
333
I'd like to offer a solution that uses CROSS APPLY to split up any delimited string in MSSQL and ROW_NUMBER() to return the 6th element. This assumes you have a table with ORGPATHTXT as a field (it can easily be converted to work without the table though):
SELECT ORGPATHTXT
FROM (
SELECT
Split.a.value('.', 'VARCHAR(100)') AS ORGPATHTXT,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY (SELECT 1)) RN
FROM
(SELECT ID, CAST ('<M>' + REPLACE(ORGPATHTXT, '/', '</M><M>') + '</M>' AS XML) AS String
FROM MyTable
) AS A
CROSS APPLY String.nodes ('/M') AS Split(a)
) t
WHERE t.RN = 6;
Here is some sample Fiddle to go along with it.
Good luck.
For sql, you can use
declare #string varchar(65) = '2123/2322/12323/111/222/333/3822'
select substring(string,25,27) from table_name
If you are using MySQL, then you can use:
select substring_index(orgpathtxt, '/', 6)
Let me just say that it is less convenient in most other databases.
Also you can use option with dynamic management function sys.dm_fts_parser
DECLARE #s nvarchar(50) = '2123/2322/12323/111/222/333/3822'
SELECT display_term
FROM sys.dm_fts_parser('"'+ #s + '"', 1033, NULL, 0)
WHERE display_term NOT LIKE 'nn%' AND occurrence = 6