|
I have many strings that need to be cut\split according to one basic rule - split\ cut between the 1st ";" to the 2nd ";" and than paste it under new column.
for examples one of my rows data is:
Y 4+2 A SAMPLES; Res 50Xp3 TP; HRI ; Bin n/a; Skew: RS; Source: Y805 [100] (Qty 100);
from this row I should retrieve: "Res 50Xp3 TP"
I think I tried all split option without success I also tried to use PATINDEX\CHARINDEX and it didn't help.
Thanks,
One options is using a little XML
Example
Declare #YourTable table (ID int,SomeCol varchar(max))
Insert Into #YourTable values
(1,'Y 4+2 A SAMPLES; Res 50Xp3 TP; HRI ; Bin n/a; Skew: RS; Source: Y805 [100] (Qty 100);')
Select ID
,NewValue = ltrim(rtrim(convert(xml,'<x>'+replace(SomeCol,';','</x><x>')+'</x>').value('/x[2]','varchar(100)')))
From #YourTable
Returns
ID NewValue
1 Res 50Xp3 TP
i've done things like this in my scripts using combination of CHARINDEX and SUBSTRINGs
DECLARE #str VARCHAR(200) = 'Y 4+2 A SAMPLES; Res 50Xp3 TP; HRI ; Bin n/a; Skew: RS; Source: Y805 [100] (Qty 100)'
DECLARE #char VARCHAR(1) = ';'
SELECT
SUBSTRING(
LTRIM(SUBSTRING(#str,CHARINDEX(#char, #str)+1, LEN(#str)-CHARINDEX(#char, #str))),
0,
CHARINDEX(#char, LTRIM(SUBSTRING(#str,CHARINDEX(#char, #str)+1, LEN(#str)-CHARINDEX(#char, #str))))
)
output
Res 50Xp3 TP
in reference to the comments
SELECT
SUBSTRING(
LTRIM(SUBSTRING(v.description,CHARINDEX(';', v.description)+1, LEN(v.description)-CHARINDEX(';', v.description))),
0,
CHARINDEX(';', LTRIM(SUBSTRING(v.description,CHARINDEX(';', v.description)+1, LEN(v.description)-CHARINDEX(';', v.description))))
) AS 'YourText'
FROM vw_public_vpo AS v
Related
I have a table that has a column like the one below
url
----------------
dir=mp3\cat152AB&fileName=file-01.mp3
dir=mp3\cat2500DfDD00&fileName=file-02.mp3
dir=mp3\cat4500f0655&fileName=file-03.mp3
...
How can I delete extra strings and arrange the fields as follows in SQL Server.
url
----------------
file-01
file-02
file-03
...
you can use charindex and substring :
SELECT substring ('dir=mp3\cat152AB&fileName=file-01.mp3', CHARINDEX('fileName=', 'dir=mp3\cat152AB&fileName=file-01.mp3') +9 ,
LEN('dir=mp3\cat152AB&fileName=file-01.mp3')-CHARINDEX('fileName=', 'dir=mp3\cat152AB&fileName=file-01.mp3')
) AS MatchPosition;
CHARINDEX and SUBSTRING can help you, please check the example:
select substring (field, charindex (';fileName=', field) + len (';fileName='), len (field) - len ('.mp3') + 1 - charindex (';fileName=', field) - len (';fileName='))
from (
select 'dir=mp3\cat152AB&fileName=file-01.mp3' field union all
select 'dir=mp3\cat2500DfDD00&fileName=file-02.mp3' union all
select 'dir=mp3\cat4500f0655&fileName=file-03.mp3'
) a
The information you want always seems to be the 11th to 5th characters before the end of the string. I would suggest a simple solution:
select left(right(url, 11), 7)
Here is a db<>fiddle.
Please try the following method.
It is using tokenization via XML/XQuery.
SQL
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, url VARCHAR(255));
INSERT INTO #tbl (url) VALUES
('dir=mp3\cat152AB&fileName=file-01.mp3'),
('dir=mp3\cat2500DfDD00&fileName=file-02.mp3'),
('dir=mp3\cat4500f0655&fileName=file-03.mp3');
-- DDL and sample data population, end
DECLARE #separator CHAR(1) = '=';
SELECT id, url
, LEFT(x, CHARINDEX('.', x) - 1) AS Result
FROM #tbl
CROSS APPLY (SELECT CAST('<root><r><![CDATA[' +
REPLACE(url, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c)
CROSS APPLY (VALUES (c.value('(/root/r[last()]/text())[1]', 'VARCHAR(100)'))) AS t2(x);
Output
+----+------------------------------------------------+---------+
| id | url | Result |
+----+------------------------------------------------+---------+
| 1 | dir=mp3\cat152AB&fileName=file-01.mp3 | file-01 |
| 2 | dir=mp3\cat2500DfDD00&fileName=file-02.mp3 | file-02 |
| 3 | dir=mp3\cat4500f0655&fileName=file-03.mp3 | file-03 |
+----+------------------------------------------------+---------+
I know we have an accepted answer but I wanted to chime in with another simple, high-performing solution that addresses file names and file extensions with various lengths. For fun I included a parameter that allows you to include the file extension if you choose.
--==== Easily Consumable Sample Data
DECLARE #link TABLE ([url] VARCHAR(100) UNIQUE);
INSERT #link VALUES ('dir=mp3\cat152AB&fileName=file-01.mp3'),
('dir=mp3\cat2500DfDD00&fileName=file-02.mp3'),
('dir=mp3\cat4500f0655&fileName=file-03.mp3'),
('dir=mp3\cat4500f0655&fileName=file-999.mp3'),
('dir=mp3\cat4500d9997&fileName=file-0021.prodigi');
--==== Allows you to determine if you want the file extension
DECLARE #exclude BIT=1;
SELECT l.[url], TheFile = SUBSTRING(l.[url], s.Pos, s.Ln-s.Pos- ((#exclude*(fl.Ln)-1)))
FROM #link AS l
CROSS APPLY (VALUES(CHARINDEX('.',REVERSE(l.[url])))) AS fl(Ln)
CROSS APPLY (VALUES(CHARINDEX('fileName=',l.[url])+9, LEN(l.[url]))) AS s(Pos,Ln);
#exclude=1 returns:
url TheFile
----------------------------------------------------- --------------
dir=mp3\cat152AB&fileName=file-01.mp3 file-01
dir=mp3\cat2500DfDD00&fileName=file-02.mp3 file-02
dir=mp3\cat4500d9997&fileName=file-0021.prodigi file-0021
dir=mp3\cat4500f0655&fileName=file-03.mp3 file-03
dir=mp3\cat4500f0655&fileName=file-999.mp3 file-999
#exclude=0 returns:
url TheFile
----------------------------------------------------- --------------
dir=mp3\cat152AB&fileName=file-01.mp3 file-01.mp3
dir=mp3\cat2500DfDD00&fileName=file-02.mp3 file-02.mp3
dir=mp3\cat4500d9997&fileName=file-0021.prodigi file-0021.prodigi
dir=mp3\cat4500f0655&fileName=file-03.mp3 file-03.mp3
dir=mp3\cat4500f0655&fileName=file-999.mp3 file-999.mp3
I have a table like this :
create table Fbank (id int, COCODE nvarchar(max))
insert into Fbank
values (1, '<row xml:space="preserve" id="174580000041250.040002">
<c1>HTG115960001</c1>
<c2>14013514,48</c2>
<c3>222</c3>
<c4>BAL MIGRATED</c4>
<c5>NULL</c5>
<c6>NULL</c6>
<c7>NULL</c7>
<c8>9900</c8>
<c9>11596</c9>
<c10>20151017</c10>
<c11>HTG</c11>
<c12>NULL</c12>
<c13>NULL</c13>
<c14>FT1529010083</c14>
<c15>1</c15>
<c16>FT1529010083</c16>
<c17>FT</c17>
<c18>20151017</c18>
<c19>NULL</c19>
<c20>0</c20>
<c21>5033_INPUTTER__OFS_AUTO.FT</c21>
<c22>5033_INPUTTER_OFS_AUTO.FT</c22>
<c23>1510181127</c23>
<c24>HG0010001</c24>
</row>')
I need to replace the string inside the tag c24 tag..
Excepted output: I need to replace the letter 'G' to be replaced with 'T' like this inside c24 tag - HT0010001 and all the rest should be same unchanged...
What I tired:
declare #searchText varchar(20) = (
select SUBSTRING(COCODE,CHARINDEX('<c24>', COCODE), 7)
from FBNK_EB_SFF_ACCT_HI000)
update Fbank
set cocode = STUFF(#searchText, CHARINDEX('<c24>', COCODE), 1, 'T')
If the code always begins with 'H', then I imagine it's easier to just have '<c24>H' be part of the string to replace, but then add it back again:
update Fbank
set COCODE = replace(cocode, '<c24>HG', '<c24>HT');
If it doesn't, then I'd say you're on the right track with charindex and substring. But use patindex instead, and update fbank directly, don't put the search term into any variable. If you're trying to split up your logic into parts, consider cross apply:
update fb
set cocode = stuff(cocode, ix, 1, 'T')
from Fbank fb
cross apply (select ix = patindex('%<c24>%', cocode) + 6) ap
where substring(cocode, ix, 1) = 'G'
I have below data in a column of a table, I want to split it into further columns.
| is used as the separator in this scenario . Column header should be before : & after column is its value.
Column
-----------------------------------------------------------------------------
ID: 30000300 | Name: India | Use: New Use
ID: 30000400 | Name: Aus | New ID: 15625616 | Address 1: NEW Rd
ID: 30000400 | Name: USA | City: VIA ARAMAC | New ID: 123
ID: 30000500 | Name: Russia | New ID: 15624951 | Address 2: 2131 BEAUDESERT
Output should be:
ID Name Use New ID City Address 1 Address 2 New City
----------------------------------------------------------------------
30000300 India New Use
30000400 Aus 15625616 NEW Rd
30000400 USA 15625616 VIA ARAMAC GALILEE
30000500 Russia 15624951 2131 BEAUDESERT
You have several rows that contain key value pairs inside an nvarchar column, but you want a table that has a header based on the keys and then rows containing just the values, sans keys. There is first the issue of an input like Key1: Value1 | Key2: Value2. Should this be returned as
Key1 Key2
Value1 NULL
NULL Value2
or is this not a possible scenario? Either way, there is the issue of generating a table with dynamic column names.
The problem with your question is that this is not a scenario that would normally be solved via SQL. You should get the data in your programming language of choice, then use regular expressions or split methods to get what you need.
If you insist doing it via SQL, then the solution is to turn the original lines input into another string, that you then sp_executesql (https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql), but I do NOT recommend it.
Here is a partial answer that you can use to return the n-th entry in a delimited string:
DECLARE #DelimitedString VARCHAR(8000);
DECLARE #Delimiter VARCHAR(100);
DECLARE #indexToReturn INT;
DECLARE #tblArray TABLE
(
ElementID INT IDENTITY(1, 1), -- Array index
Element VARCHAR(1000) -- Array element contents
);
-- Local Variable Declarations
-- ---------------------------
DECLARE #Index SMALLINT,
#Start SMALLINT,
#DelSize SMALLINT;
SET #DelSize = LEN(#Delimiter + 'x') - 1;
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(#DelimitedString) > 0
BEGIN
SET #Index = CHARINDEX(#Delimiter, #DelimitedString);
IF #Index = 0
BEGIN
INSERT INTO #tblArray
(
Element
)
VALUES
(LTRIM(RTRIM(#DelimitedString)));
BREAK;
END;
ELSE
BEGIN
INSERT INTO #tblArray
(
Element
)
VALUES
(LTRIM(RTRIM(SUBSTRING(#DelimitedString, 1, #Index - 1))));
SET #Start = #Index + #DelSize;
SET #DelimitedString = SUBSTRING(#DelimitedString, #Start, LEN(#DelimitedString) - #Start + 1);
END;
END;
DECLARE #val VARCHAR(1000);
SELECT #val = Element
FROM #tblArray AS ta
WHERE ta.ElementID = #indexToReturn;
SELECT #val;
Situation: I have a column where each cell can have up to 5 delimiters. However, it's possible that there are none.
Objective: How do i handle errors such as :
Invalid length parameter passed to the LEFT or SUBSTRING function.
in the case that it cannot find the specified delimiter.
Query:
declare #text VARCHAR(111) = 'abc-def-geeee-ifjf-zzz'
declare #start1 as int
declare #start2 as int
declare #start3 as int
declare #start4 as int
declare #start_index_reverse as int
set #start1 = CHARINDEX('-',#text,1)
set #start2 = CHARINDEX('-',#text,charindex('-',#text,1)+1)
set #start3 = CHARINDEX('-',#text,charindex('-',#text,CHARINDEX('-',#text,1)+1)+1)
set #start4 = CHARINDEX('-',#text,charindex('-',#text,CHARINDEX('-',#text,CHARINDEX('-',#text,1)+1)+1)+1)
set #start_index_reverse = CHARINDEX('-',REVERSE(#text),1)
select
LEFT(#text,#start1-1) AS Frst,
SUBSTRING(#text,#start1+1,#start2-#start1-1) AS Scnd,
SUBSTRING(#text,#start2+1,#start3-#start2-1) AS Third,
SUBSTRING(#text,#start3+1,#start4-#start3-1)AS Third,
RIGHT(#text,#start_index_reverse-1) AS Lst
In this case my variable includes 5 delimiters and so my query works but if i removed one '-' it would break.
XML support in SQL Server brings about some unintentional but useful tricks. Converting this string to XML allows for some parsing that is far less messy than native string handling, which is very far from awesome.
DECLARE #test varchar(111) = 'abc-def-ghi-jkl-mnop'; -- try also with 'abc-def'
;WITH n(x) AS
(
SELECT CONVERT(xml, '<x>' + REPLACE(#test, '-', '</x><x>') + '</x>')
)
SELECT
Frst = x.value('/x[1]','varchar(111)'),
Scnd = x.value('/x[2]','varchar(111)'),
Thrd = x.value('/x[3]','varchar(111)'),
Frth = x.value('/x[4]','varchar(111)'),
Ffth = x.value('/x[5]','varchar(111)')
FROM n;
For a table it's almost identical:
DECLARE #foo TABLE ( col varchar(111) );
INSERT #foo(col) VALUES('abc-def-ghi-jkl-mnop'),('abc'),('def-ghi');
;WITH n(x) AS
(
SELECT CONVERT(xml, '<x>' + REPLACE(col, '-', '</x><x>') + '</x>')
FROM #foo
)
SELECT
Frst = x.value('/x[1]','varchar(111)'),
Scnd = x.value('/x[2]','varchar(111)'),
Thrd = x.value('/x[3]','varchar(111)'),
Frth = x.value('/x[4]','varchar(111)'),
Ffth = x.value('/x[5]','varchar(111)')
FROM n;
Results (sorry about the massive size, seems this doesn't handle 144dpi well):
add a test before your last select
then you should decide how to handle the other case (when one of start is 0)
You can also refer to this link about splitting a string in sql server
which is uses a loop and can handle any number of delimiters
if #start1>0 and #start2>0 and #start3>0 and #start4>0
select LEFT(#text,#start1-1) AS Frst,
SUBSTRING(#text,#start1+1,#start2-#start1-1) AS Scnd,
SUBSTRING(#text,#start2+1,#start3-#start2-1) AS Third,
SUBSTRING(#text,#start3+1,#start4-#start3-1)AS Third,
RIGHT(#text,#start_index_reverse-1) AS Lst
Hi i have the string llike,
"on 01-15-09 witha factor of 0.8"
i wanted to seperate this string in the follwing way,
1] date as 01-15-09
2] Factor of 0.8
NOTE : String length is not fixed.
so how can we seperate the data in the form of #1 & #2 ?
To get the date you can use PATINDEX().
declare #yourString varchar(100)
set #yourString = 'on 01-15-09 with a factor of 0.8'
select substring(#yourString,
patindex('%[0-9][0-9]-[0-9][0-9]-[0-9][0-9]%', #yourString),
8)
To get "factor of xx" you can do:
select substring(#yourString,
patindex('%with a%', #yourString) + 7,
20)
declare #txt varchar(max)
set #txt = 'on 01-15-09 witha factor of 0.8'
select cast(substring(#txt, patindex('% [0-9][1-9]-%', #txt), 9) as date) [date],
cast(right(#txt, patindex('%_ %', reverse(#txt))) as decimal(9,1)) Factor
Result:
date Factor
---------- ------
2009-01-15 0.8