Select the first word on the left of a string in snowflake - sql

I have a column (mycolumn) in my snowflake table (mytable) whose content has this pattern :
JohnDoe - Client Number One
MaryJane - Client Number Two
I would need to extract the first portion on the left of the string (JohnDoe,MaryJane - with no whitespace behind).
I tried to use the following approach, but I got stucked because I could only remove the first two block of words to the right, but not the - (dash) and the white spaces.
select substring(mycolumn,1,length(mycolumn)- CHARINDEX(' ', REVERSE(mycolumn))- CHARINDEX(' ', REVERSE(mycolumn))) from mytable

You can use regexp_substr():
select regexp_substr(mycolumn, '^[^ ]+')
from mytable;

Related

Impala / Hive - Extract text from comma delimited string where each separation doesnt match a pattern

is there a way in hive or impala to extract a string from a delimited string but only where the string i want doesnt match one or multiple patterns?
For instance, i have a field with IPs (the number varies depending on network adapters):
169.254.182.175,192.168.0.1,10.199.44.111
I would like to extract the IP that doesnt start with 169.254. (there could be many of these) and doesnt equal 192.168.0.1
The IPs can be in any order as well.
I tried doing substr with nested cases but due the unknown number of ips in the string it didnt work out.
Could this be accomplished with regex_extract or something similar?
Thanks,
You may use regexp_replace with capturing group for patterns that you do not want to keep and specify only groups of interest in the replacement string.
See example below in Impala (impalad version 3.4.0):
select
addr_list,
/*Concat is used just for visualization*/
rtrim(ltrim(regexp_replace(addr_list,concat(
/*Group of 169.254.*.* that should be excluded*/
'(169\\.254\\.\\d{1,3}\\.\\d{1,3})', '|',
/*Another group for 192.168.0.1*/
'(192\.168\.0\.1)', '|',
/*And the group that we need to keep*/
'(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})'
/*So keep the third group in the output.
Other groups will be replaced with empty string*/
), '\\3'), ','), ',') as ip_whitelist
from(values
('169.254.182.175,192.168.0.1,169.254.2.12,10.199.44.111,169.254.0.2' as addr_list),
('10.58.3.142,169.254.2.12'),
('192.168.0.1,192.100.0.2,154.16.171.3')
) as t
addr_list
ip_whitelist
169.254.182.175,192.168.0.1,169.254.2.12,10.199.44.111,169.254.0.2
10.199.44.111
10.58.3.142,169.254.2.12
10.58.3.142
192.168.0.1,192.100.0.2,154.16.171.3
192.100.0.2,154.16.171.3
regexp_extract works differently for unknown reason, because the same regex with 3 as return group doesn't return anything at all for case 1 and 3.
select
t.addr_list,
rtrim(ltrim(regexp_replace(addr_list, r.regex, '\\3'), ','), ',') as ip_whitelist,
regexp_extract(addr_list, r.regex, 3) as ip_wl_extract
from(values
('169.254.182.175,192.168.0.1,169.254.2.12,10.199.44.111,169.254.0.2' as addr_list),
('10.58.3.142,169.254.2.12'),
('192.168.0.1,192.100.0.2,154.16.171.3')
) as t
cross join (
select concat(
'(169\\.254\\.\\d{1,3}\\.\\d{1,3})', '|',
'(192\.168\.0\.1)', '|',
'(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})'
) as regex
) as r
addr_list
ip_whitelist
ip_wl_extract
169.254.182.175,192.168.0.1,169.254.2.12,10.199.44.111,169.254.0.2
10.199.44.111
10.58.3.142,169.254.2.12
10.58.3.142
10.58.3.142
192.168.0.1,192.100.0.2,154.16.171.3
192.100.0.2,154.16.171.3

SQL- Remove Trailing space and add it to the beginning of the Name

Was working on SQL-EX.ru exercises.
There is one question for DML that I could not do, but I cannot proceed to the next one, until this one is done.
the question itself: All the trailing spaces in the name column of the Battles table remove and add them at the beginning of the name.
My code:
Update Battles
set name=concat(' ',(LTRIM(RTRIM(name))))
The system does not let it go through, I understand that I am using ' ' for the concat, whereas I need to use the stuff that got trimmed. And I have no idea how...
Any help would be very much appreciated
Try Something Like:-
set name = lpad(trim(name), length(trim(name))+4, ' ')
Here use TRIM to remove space from both side. use LPAD to add something on left side with n (4) chars
I'm not familiar with SQL-EX.ru, but if it's Oracle compatible and you can use regular expressions (or you are at that point in the training) here's a way. Maybe it'll give you an idea at least. The first part is just setup and uses a WITH clause to create a table (like a temp table in memory, actually called a Common Table Expression or CTE) called battles containing a name column with 2 rows. Each name column datum has a different number of spaces at the end. Next select from that column using a regular expression that uses 2 "remembered" groups surrounded by parentheses, the first containing the string up to until but not including the first space, the second containing 0 or more space characters anchored to the end of the line. Replace that with the 2nd group (the spaces) first, followed by the first group (the first part of the string). This is surrounded by square brackets just to prove in the output the same spaces were moved to the front of the string.
SQL> with battles(name) as (
select 'test2 ' from dual union
select 'test1 ' from dual
)
select '[' || regexp_replace(name, '(.*?)([ ]*)$', '\2\1') || ']' fixed
from battles;
FIXED
----------------------------------------------------------------------------
[ test1]
[ test2]
SQL>
I hope this solution can be applied to your problem or at least give you some ideas.
Try this:
set name = case when len(name) > len(rtrim(name))
then replicate(' ', len(name) - len(rtrim(name))) + rtrim(name)
else name
end
update battles
set name = case when (len(name+'a')-1) > len(rtrim(name))
then
replicate(' ',
(len(name+'a')-1) - len(rtrim(name))) + rtrim(name)
else name
end
Len() doesn't count trailing spaces. So using (len(name+'a')-1).
Simplest answer:
UPDATE Battles
SET name = SPACE(DATALENGTH(name)-DATALENGTH(RTRIM(name))) + RTRIM(name)
But only works because name is VARCHAR.
More generic is to do:
UPDATE Battles
SET name = SPACE(len(name+'x')-1-len(RTRIM(name))) + RTRIM(name)
simple example below ... enjoy :)
update battles set name =
Space( DATALENGTH(name) - DATALENGTH(rtrim(name))) + rtrim(name)
where date in ( select date from battles)

Extract first word from a varchar column and reverse it

I have following data in my table
id nml
-- -----------------
1 Temora sepanil
2 Human Mixtard
3 stlliot vergratob
I need to get the result by extracting first word in column nml and get its last 3 characters with reverse order
That means output should be like
nml reverse
----------------- -------
Temora sepanil aro
Human Mixtard nam
stlliot vergratob toi
You use PostgreSQL's string functions to achieve desired output
in this case am using split_part,right,reverse function
select reverse(right(split_part('Temora sepanil',' ',1),3))
output:
aro
so you can write your query in following format
select nml
,reverse(right(split_part(nml,' ',1),3)) "Reverse"
from tbl
Split nml using regexp_split_to_array(string text, pattern text [, flags text ]) refer Postgres Doc for more info.
Use reverse(str) (refer Postgres Doc) to reverse the first word form previous split.
Use substr(string, from [, count]) (refer Postgres Doc) to select first three letters of the reversed test
Query
SELECT
nml,
substr(reverse(regexp_split_to_array(nml, E'\\s+')[0]),3) as reverse
FROM
MyTable
You can use the SUBSTRING, CHARINDEX, RIGHT and REVERSE function
here's the syntax
REVERSE(RIGHT(SUBSTRING(nml , 1, CHARINDEX(' ', nml) - 1),3))
sample:
SELECT REVERSE(RIGHT(SUBSTRING(nml , 1, CHARINDEX(' ', nml) - 1),3)) AS 'Reverse'
FROM TableNameHere

trim the column value string

In SQL Query, I need the values as below using select query of my column.
Result has to be the text after the first space ' ' and before the first '('
Source Column
create Table Test_Table (Column1 Varchar(50))
Insert into Test_Table Values
('0636 KAVITHI (LOC)'),
('0638 SRI KRISHNA (NAT)'),
('0639 SELVAM'),
('0643 GOOD SERVICE (LOC)'),
('0644 FINA CARE EVENT (LOC)')
I need get the string found between first ' ' and the '('
Expected Result
KAVITHI
SRI KRISHNA
SELVAM
GOOD SERVICE
FINA CARE EVENT
Another approach without using an OUTER APPLY.
SELECT CASE WHEN Column1 LIKE '%(%'
THEN SUBSTRING(RIGHT(Column1,LEN(Column1)-CHARINDEX(' ',Column1)),0,
CHARINDEX('(',RIGHT(Column1,LEN(Column1)-CHARINDEX(' ',Column1)),0))
ELSE RIGHT(Column1,LEN(Column1)-CHARINDEX(' ',Column1))
END AS Trimmed
FROM Test_Table
OUTPUT
Trimmed
KAVITHI
SRI KRISHNA
SELVAM
GOOD SERVICE
FINA CARE EVENT
SQL Fiddle: http://sqlfiddle.com/#!3/69dd1/20/0
CHARINDEX() can be used to find the position of specific characters.
OUTER APPLY can be used to find the position of the space and brace characters, and store them in a place that you can re-use them.
SUBSTRING() can be used to find the text between the space and the brace.
EDIT: Added CASE to cope with values that contain no (.
SELECT
SUBSTRING(
test_table.column1, -- the field we're searching
stats.idx_space + 1, -- starting from the character after the first space
CASE
WHEN stats.idx_brace > stats.idx_space
THEN stats.idx_brace
ELSE stats.idx_eos
END
-
stats.idx_space -- for as many characters as there are between the space and the brace
)
FROM
test_table
OUTER APPLY
(
SELECT
CHARINDEX(' ', test_table.column1) AS idx_space, -- position of the first space
CHARINDEX('(', test_table.column1) AS idx_brace, -- position of the first brace
LEN(test_table.column1) AS idx_eos -- position of the end-of-string
)
AS stats
EDIT: A single "line", as requested.
Do note that forcing this as a single line does make this harder to read, maintain and adapt. One of APPLY's strongest use-cases is to maintain DRY (Don't Repeat Yourself) principles.
This query repeats several parts several times:
- find the first space repeated 2 times
- find the first brace repeated 3 times
SELECT
SUBSTRING(
test_table.column1,
CHARINDEX(' ', test_table.column1) + 1,
CASE
WHEN CHARINDEX('(', test_table.column1) > CHARINDEX(' ', test_table.column1)
THEN CHARINDEX('(', test_table.column1)
ELSE LEN(test_table.column1)
END
-
CHARINDEX('(', test_table.column1)
)
FROM
test_table

Update one column from substring of another column

I have an existing column that I would like to take a subset of and insert into a second (new) column in the same table.
e.g. MyTable.[FullName] (existing column) contains a string like "P-13-146 PS - Goodyear - Tire repair"
I created a new column, MyTable.[ShortName] that I want to insert a substring of the value from the first column into ("P-13-146 PS"). The problem is that the length of the substring is different for each full name. The only real consistency is that I want up to the second whitespace character.
I am trying to resolve the following:
UPDATE [MyTable] SET [ShortName] = ???
Try this:
declare #exp varchar(200)
set #exp='P-13-146 PS - Goodyear - Tire repair'
select RTRIM(SUBSTRING(#exp,1,CHARINDEX(' ',#exp,charindex(' ',#exp)+1)))
Just combine the string manipulation functions until you get what you want:
SELECT
CASE WHEN CHARINDEX(' ',FullName, CHARINDEX(' ', FullName)+1) = 0 THEN FullName
ELSE SUBSTRING(FullName, 1, CHARINDEX(' ',FullName, CHARINDEX(' ', FullName)+1)-1)
END ShortName
FROM MyTable
The first part of the CASE statement is for names that have fewer than two spaces.