SQL Select everything to the left of a character - sql

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)))

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;

TSQL extract part of string with regex

i would make a script that iterate over the records of a table with a cursor
and extract from a column value formatted like that "yyy://xx/bb/147011"
only the final number 147011and to put this value in a variable.
It's possible to do something like that?
Many thanks.
You don't need a cursor for this. You can just use a query. The following gets everything after the last /:
select right(str, charindex('/', reverse(str)) - 1 )
from (values ('yyy://xx/bb/147011')) v(str)
It does not specifically check if it is a number, but that can be added as well.
You can also use the below query.
SELECT RIGHT(RTRIM('yyy://xx/bb/147011'),
CHARINDEX('/', REVERSE('/' + RTRIM('yyy://xx/bb/147011'))) - 1) AS LastWord
If numeric value has exact position defined with sample data, then you can do :
SELECT t.*, SUBSTRING(t.col, PATINDEX('%[0-9]%', t.col), LEN(t.col))
FROM table t;

What's the equivalent of Excel's `left(find(), -1)` in BigQuery?

I have names in my dataset and they include parentheses. But, I am trying to clean up the names to exclude those parentheses.
Example: ABC Company (Somewhere, WY)
What I want to turn it into is: ABC Company
I'm using standard SQL with google big query.
I've done some research and I know big query has left(), but I do not know the equivalent of find(). My plan was to do something that finds the ( and then gives me everything to the left of -1 characters from the (.
My plan was to do something that finds the ( and then gives me everything to the left of -1 characters from the (.
Good plan! In BigQuery Standard SQL - equivalent of LEFT is SUBSTR(value, position[, length]) and equivalent of FIND is STRPOS(value1, value2)
With this in mind your query can look like (which is exactly as you planned)
#standardSQL
WITH names AS (
SELECT 'ABC Company (Somewhere, WY)' AS name
)
SELECT SUBSTR(name, 1, STRPOS(name, '(') - 1) AS clean_name
FROM names
Usually, string functions are less expensive than regular expression functions, so if you have pattern as in your example - you should go with above version
But in more generic cases, when pattern to clean is more dynamic like in Graham's answer - you should go with solution in Graham's answer
Just use REGEXP_REPLACE + TRIM. This will work with all variants (just not nested parentheses):
#standardSQL
WITH
names AS (
SELECT
'ABC Company (Somewhere, WY)' AS name
UNION ALL
SELECT
'(Somewhere, WY) ABC Company' AS name
UNION ALL
SELECT
'ABC (Somewhere, WY) Company' AS name)
SELECT
TRIM(REGEXP_REPLACE(name,r'\(.*?\)',''), ' ') AS cleaned
FROM
names
Use REGEXP_EXTRACT:
SELECT
RTRIM(REGEXP_EXTRACT(names, r'([^(]*)')) AS new_name
FROM yourTable
The regex used here will greedily consume and match everything up until hitting an opening parenthesis. I used RTRIM to remove any unwanted whitespace picked up by the regex.
Note that this approach is robust with respect to the edge case of an address record not having any term with parentheses. In this case, the above query would just return the entire original value.
I can't test this solution at the moment, but you can combine SUBSTR and INSTR. Like this:
SELECT CASE WHEN INSTR(name, '(') > 0 THEN SUBSTR( name, 1, INSTR(name, '(') ) ELSE name END as name FROM table;

SQL Replace command with wildcards

Basically I'm trying to replace everything in a string that is within brackets.
So for example the string of '123[1abc]abc' would become '123[xx]abc'
select replace(string,'[%]','[xx]') as string2 from table1
Except of course that won't work.
The value within the brackets is always different, and it is simply not feasible to find all the individual possibilities. In addition, some of the values within the brackets also appear outside of the brackets, but I only want them changed for the part within.
I'm working in Microsoft SQL Server if that makes any difference.
Assuming there is only one such expression and the square braces only appear once, you can use stuff() to construct the string:
select stuff(str,
charindex('[', str) + 1,
charindex(']', str) - charindex('[', str) - 1,
'xx')
You could do it with string manipulation. Take the left of the string up to the left bracket, add 'xx' and then add the right side starting with the right bracket.
SELECT LEFT(string, CHARINDEX('[', string))
+ 'xx'
+ RIGHT(string, LEN(string) - CHARINDEX(']', string) + 1) AS string2
FROM table1;

how to use PARSENAME

I get not the right result out of:
select parsename(replace('K.03.2_test', '_', '.' ), 2)
My result at the moment is:
2
...but I need all the string to the left from the underscore. So this is what I need:
K.03.2
To get the characters to the left of the underscore you can use
SELECT CASE
WHEN YourCol LIKE '%[_]%'
THEN LEFT(YourCol, CHARINDEX('_', YourCol) - 1)
END
FROM YourTable
parsename is designed to parse object identifiers not split arbitrary strings.