SQL Server - Splitting a string - sql

I have the below string which is currently in one column, called Column1, in a table called dbo.faresnumb
Column1
512.65USD/52.65USD/0167025354825
I want to create three new columns from this string called Fare1, Fare2, Number1 like below
Fare1 Fare2 Number1
512.65USD 52.65USD 0167025354825
So the delimter is the / and the character count will not always be the exact same. For example, Fare1 could be 54.00USD rather than 512.65USD and I still need to capture everything before the first /. I know is SAS there is a way to scan a substring to find a delimiter and assign new variables, but I am new to SQL. Any help would be much appreciated!
Thanks,
Bennett

Such string operations are a pain in SQL Server. You can do:
select parts.part1 as fare1,
left(rest, charindex('/', rest) - 1) as fare2,
stuff(rest, 1, charindex('/', rest), '') as number1
from t cross apply
(values (left(col, charindex('/', col) - 1),
stuff(col, 1, charindex('/', col), '')
)
) parts(part1, rest);
Here is a rextester.
Sadly, SQL Server 2016 offers split_string() which makes this simpler. The sad part is that it does not return the position of the substring in the string. That is needed to ensure that the three extracted values are in the right order.

One more way to achieve the same using a bit of XML -
select cast(concat('<x>', REPLACE(Column1, '/', '</x><x>'), '</x>') as xml).value('/x[1]','varchar(100)'),
cast(concat('<x>', REPLACE(Column1, '/', '</x><x>'), '</x>') as xml).value('/x[2]','varchar(100)'),
cast(concat('<x>', REPLACE(Column1, '/', '</x><x>'), '</x>') as xml).value('/x[3]','varchar(100)') from dbo.faresnumb

Related

How trim() works in SQL Server

I have a column SysTraNo with some specific data like
HO/20-21/DRP/0001
215/21-22/AGP/0003
I want to trim that whole column and only take 20-21 or 21-22 of that data. How can I do this?
Using the base string functions we can try:
SELECT val,
SUBSTRING(val,
CHARINDEX('/', val) + 1,
CHARINDEX('/', val, CHARINDEX('/', val) + 1) -
CHARINDEX('/', val) - 1) AS nums
FROM yourTable;
Demo
The logic here is to take a substring starting from the character after the first / until the character before the second /. On other databases, we could have used regular expressions, but SQL Server has no native support for this.
In sql server trim works like below.
As one example is above Here I have given another example using substring on email to extract the domain part.
SELECT
email,
SUBSTRING(
email,
CHARINDEX('#', email)+1,
LEN(email)-CHARINDEX('#', email)
) domain
FROM
practice
ORDER BY
email;

Get text after second occurrence of a specific character

I have a column with data like this:
firstNameLetter_surname_numericCode
For example:
m_johnson_1234
I need to extract the numeric code. I've tried with SUBSTRING function but I just get:
surname_numericCode
This is the code I've used:
SET number = substring(t2.code, charindex('_', t2.code, 2) + 1, len(t2.code))
How can I get just the numeric code?
Heres a one-liner for you
select right('m_johnson_1234', charindex('_', reverse('m_johnson_1234') + '_') - 1)
Call the CHARINDEX function twice:
SELECT SUBSTRING(
code,
NULLIF(CHARINDEX('_', code, NULLIF(CHARINDEX('_', code), 0) + 1), 0) + 1,
LEN(code)
)
FROM (VALUES
('a_b_c'),
('a_b')
) x(code)
One method is to look for the first _ in the reversed string:
select col,
stuff(col, 1, len(col) - charindex('_', reverse(col)) + 1, '') as numericCode
from (values ('firstNameLetter_surname_numericCode')) v(col);
If the numeric code is really a number -- and no other numbers start the preceding values -- then you can use patindex():
select col,
stuff(col, 1, patindex('%[_][0-9]%', col), '') as numericCode
from (values ('firstNameLetter_surname_0000')) v(col);
The SUBSTR and INSTR functions can be combined to get you the numeric code.
SELECT SUBSTR('m_johnson_1234', INSTR('m_johnson_1234', '_', 1, 2)+1) FROM TABLE;
For the start_pos argument use INSTR to start at the beginning of the string, and find the index of the second instance of the '_' character. Then use that to start one position after and read to the end of the string.
If you need the result to be numeric instead of still a string, then wrap the SUBSTR() in a TO_NUMBER() function.
Late answer, and just because I didn't see PARSENAME() mentioned.
Example
Select parsename(replace(t2.code,'_','.'),1)
From YourTable

SQL Select everything to the left of a character

I need to select everything to the left of a hyphen in a string, but some strings have 2 hyphens, in which case I need to select everything to the left of the second hyphen.
The strings are never the same length and some strings don't have hyphens at all.
Example data:
Manager-News Delivery
Co-Host-Television
Expected results:
Manager
Co-Host
How about just removing everything from the last hyphen onward?
You can do that with stuff():
select stuff(str, len(str) - charindex('-', reverse(str)) + 1, len(str), '')
from (values ('Co-Host-Television'), ('Manager-News Delivery')) v(str);
Or better yet, with left():
select left(str, len(str) - charindex('-', reverse(str)) )
from (values ('Co-Host-Television'), ('Manager-News Delivery')) v(str);
SQL isn't really meant for string manipulation, you should do that type of work in another language (on the client side? maybe).
But, it you really, really want to, and the data is small and not something you'll need to do a lot, you can use the following code:
select rtrim(reverse(substring(reverse('Manager-News Delivery'),
charindex('-',reverse('Manager-News Delivery'))+1,99)))
select rtrim(reverse(substring(reverse('Co-Host-Television'),
charindex('-',reverse('Co-Host-Television'))+1,99)))

Retrieve number from string most effective way

I'm wondering if there is better,more optimal way to retrieve a number from string
eg.
"O5_KK/text1/1239312/006_textrandom"
"O5_KK/text1/1239315/0109_textrandom123"
"O5_KK/text1/1239318/0110_textrandom432"
'O5_KK/text1' - hardcoded, never change.
1239312,1239315,1239318 - random number, unique within row
textrandom,textrandom123,textrandom432 - random string
as output I would like to get only numbers:
006
0109
0110
I know how to do it by using instr,substr,replace function. But it looks terrible to read. I'm looking for other solution, any hints ?
Thanks
You can use regexp_subtr():
select regexp_substr(val, '/[0-9]+_', 1, 1)
And then remove the extra characters:
select replace(replace(regexp_substr(val, '/[0-9]+_', 1, 1), '/', ''), '_', '')
This is simply the part after the third slash before the second underscore:
substr(str, instr(str, '/', 1, 3) + 1, instr(str, '_', 1, 2) - instr(str, '/', 1, 3) - 1)
Assuming the number you need is always between the last slash(/) and the last underscore (_), with no characters in between - as in your sample - the best solution uses just substr and instr. Note that regular expressions are slower than straight substr and instr; there are cases when the only solution is regexpr (or regexpr is much easier to write and maintain), but this is not one of those cases.
select substr(val, instr(val,'/',-1)+1, instr(val,'_',-1)-instr(val,'/',-1)-1)

How to get a id from a url using SQL QUERY. The ID changes dynamically. the database is Sql server 2008

I have url like:
http://mysites.xyz.com/_layouts/ng/ActivityStream.aspx/id/2624D92223261D370D7287C9E83CAEEA/Activity%20Stream%20Post.
I need to get the 2624D92223261D370D7287C9E83CAEEA. But not able to do so. my current query is
SUBSTRING(#URL2,LEN('http://mysites.xyz.com/_layouts/ng/ActivityStream.aspx/id/'),LEN(#URL2)-LEN('http://mysites.xyz.com/_layouts/ng/ActivityStream.aspx/id/')- CHARINDEX('/',REVERSE(#URL2))))
Please suggest.
Try this:
SELECT SUBSTRING(
#URL2,
CHARINDEX('/id/', #URL2)+4,
CHARINDEX('/', #URL2, CHARINDEX('/id/', #URL2)+5)
- (CHARINDEX('/id/', #URL2)+4))
Note: This assumes that the id is always followed by at least one more slash.
Breakdown:
The first argument of the substring is the string that contains the full expression.
The second one is the first index after /id/.
The third one is the desired length - calculated by the first index of / after /id/ - the first index after /id/.
update
To cope with strings that does not contain a slash after the id value, use case:
SELECT SUBSTRING(
#URL,
CHARINDEX('/id/', #URL)+4,
CASE WHEN CHARINDEX('/', #URL, CHARINDEX('/id/', #URL)+5) > 0 THEN
CHARINDEX('/', #URL, CHARINDEX('/id/', #URL)+5)
- (CHARINDEX('/id/', #URL)+4)
ELSE
LEN(#URL)
END
)
If the structure is always the same then you can try:
SELECT REPLACE(RIGHT(#s, LEN(#s) - 58), '/Activity%20Stream%20Post', '')
or:
SELECT REPLACE(REPLACE(#s,'/Activity%20Stream%20Post', ''), 'http://mysites.xyz.com/_layouts/ng/ActivityStream.aspx/id/', '')