get 1 email address from multiple delimiters - sql

I have a column email with multiple delimiters like space ,/ , .
email
/john#thundergroup.com.mi/chris#cup.com.ey
r.Info#bc.com / rudi.an#yy.com
Dal#pema.com/Al#ama.com
/randi#mv.com
zul#sd.com/sat#sd.com/ faze#sd.com
My query:
select email,
CASE WHEN CHARINDEX(' ', email) > 0 THEN SUBSTRING(email, 0, CHARINDEX(' ', email)) ELSE
email END as Emailnew
FROM table
my output:
/john#thundergroup.com.mi/chris#cup.com.ey
r.Info#bc.com
Dal#pema.com/Al#ama.com
/randi#mv.com
zul#sd.com/sat#sd.com/ faze#sd.com
Please suggest changes so that in a single query I'm able to extract email

To get the first email always, you can try this below logic-
DEMO HERE
SELECT
CASE
WHEN CHARINDEX('/',email,2) = 0 THEN REPLACE(email,'/','')
ELSE REPLACE(SUBSTRING(email,0,CHARINDEX('/',email,2)),'/','')
END
FROM your_table
Output will be-
john#thundergroup.com.mi
r.Info#bc.com
Dal#pema.com
randi#mv.com
zul#sd.com

On modern SQL Servers try something like:
-- Setup...
create table dbo.Foo (
FooID int not null identity primary key,
Email nvarchar(100)
);
insert dbo.Foo (Email) values
('/john#thundergroup.com.mi/chris#cup.com.ey'),
('r.Info#bc.com / rudi.an#yy.com'),
('Dal#pema.com/Al#ama.com'),
('/randi#mv.com'),
('zul#sd.com/sat#sd.com/ faze#sd.com');
go
-- Demo...
select FooID, [Email]=value
from dbo.Foo
outer apply (
select top 1 value
from string_split(translate(Email, ' /', ';;'), ';')
where nullif(value, '') is not null
) Splitzville;
Which yields:
FooID Email
1 john#thundergroup.com.mi
2 r.Info#bc.com
3 Dal#pema.com
4 randi#mv.com
5 zul#sd.com
Requirements:
SQL Server 2016 and later for string_split().
SQL Server 2017 and later for translate().

If you want the first email only, use patindex():
select email,
left(email, patindex('%[^a-zA-Z0-9#.]%', email + ' ') - 1) as Emailnew
from table;
The pattern (a-zA-Z0-9#.) are valid email characters. You may have additional ones that you care about.
Unfortunately, I notice that some of your lists start with delimiter characters. In my opinion, the above works correctly by returning an empty value. That said, your desired results are to get the second value in that case.
So, you have to start the search at the first valid email character:
select t.email,
left(v.email1, patindex('%[^-_a-zA-Z0-9#.]%', v.email1 + ' ') - 1) as Emailnew
from t cross apply
(values (stuff(t.email, 1, patindex('%[-_a-zA-Z0-9#.]%', t.email) - 1, ''))) v(email1);
Here is a db<>fiddle.

Related

How to count task like completion from one column

I have a column that contains
"*********Task list completion *******
1.test
2.test
3.
4.
5.
How do I create a SQL query to count the completion? i.e. when there is text after the "number ." > 1.Test
The above would come back with count = 2
I have tried:
SELECT id as Task
,table
,table.id
from table
where table.id like '%Tier 1 Please Insure all tasks%'
and table.id LIKE '%3._%'
I solved it like this:
SELECT COUNT(*)
FROM (
SELECT Column FROM table WHERE Column LIKE '[0-9]%._%'
) AS a
In where condition I checked that column:
must start with a number
contain a dot
after dot at least one character
Check test output here on DB FIDDLE
Update
Because you did not provide a full question at start here is my updated answer:
Before running query I created a table with data for testing
CREATE TABLE tbl (field NVARCHAR(200))
INSERT INTO tbl VALUES ('Test DGS ********** Tier 1 Please Insure all tasks are fully completed ********* 1.test 2.test 3. 4. 5. 6. ')
CREATE TABLE #pom (Word NVARCHAR(50))
I wrote main query:
DECLARE #Strings NVARCHAR(200) = (SELECT REVERSE(LEFT(REVERSE(field), charindex('*', REVERSE(field)) - 2)) FROM tbl)
WHILE LEN(#Strings) > 0
BEGIN
INSERT INTO #pom
SELECT LEFT(#Strings, CHARINDEX(' ', #Strings) -1) AS 'Word'
SET #Strings = stuff(#Strings, 1, charindex(' ', #Strings + ' '), '')
END
SELECT COUNT(*)
FROM (
SELECT Word FROM #pom WHERE Word LIKE '[0-9]%._%'
) AS a
And you can see output here:
You can create a function or stored procedure with this code or whatever you need.
You can try this:
SELECT count(*)
FROM table
WHERE table.id LIKE '[1-9]%[a-z]'
If the data is consistently in this format, you can use wildcard expressions as below.
SELECT count(*)
FROM [table]
WHERE [column] LIKE '[1-9]%[a-z]'

Query everything that comes after the '#'

I am setting up a new query but unfortunately I got stuck in some kind of functions in SQL. I have some records with specific emails. All I want is bringing everything that comes after the '#'.
For example:
cesarcastillo88#hotmail.com ==> as a result I should get the following: hotmail.com.
This was not complicated at all because of the fact that the record shows one email only.
But...what if that record includes the following emails:
cesarcastillo88#hotmail.com ; laura23#gmail.com ; test#compliance.com
I did it perfectly for those cases with only 1 email in a single record
I used the following formula:
substring(**columnName**, charindex('#', sfe.**columnName**), len(sfe.**columnName**))
However, how am I suppose to do it with 3 emails in a single record?
My desired outcome is the following:
hotmail.com ; gmail.com ; compliance.com
Here is a possible solution based on the assumption that you have some sort of ID column that could help to identify each unique row:
;with smpl as (
select *
from (values
(1, 'cesarcastillo88#hotmail.com ; laura23#gmail.com ; test#compliance.com'),
(2, 'abc#cde.net'),
(3, 'laura23#gmail.com ; test#compliance.com')) x(id, email)
), split(id, A, B) as (
select distinct id, CAST(LEFT(email, CHARINDEX(';',email+';')-1) as varchar(100)),
CAST(STUFF(email, 1, CHARINDEX(';',email+';'), '') as varchar(100))
from smpl
union all
select id, CAST(LEFT(B, CHARINDEX(';',B+';')-1) as varchar(100)),
CAST(STUFF(B, 1, CHARINDEX(';',B+';'), '') as varchar(100))
from split
where B > ''
), clr as (
select ID, substring(LTRIM(RTRIM(A)), charindex('#', LTRIM(RTRIM(A))) + 1, len(LTRIM(RTRIM(A)))) cleanEmail
--into #tempTbl
from split
), ccat as (
SELECT DISTINCT ST2.ID,
SUBSTRING(
(
SELECT ';'+ST1.cleanEmail AS [text()]
FROM clr ST1
WHERE ST1.ID = ST2.ID
ORDER BY ST1.ID
FOR XML PATH ('')
), 2, 1000) Emails
FROM clr ST2
)
select * from ccat
And here is some explanation on how this all works:
First CTE expression splits emails into separate rows using ; as a separator
Second CTE is based on your function to remove the recipient from email address and only leave the domain
The last one concatenates everything back and uses same ; as separator. Feel free to add extra spaces around if that's your preferred output.
You don't say what version of SQL Server, but I'll assume 2016 or newer. They key is the STRING_SPLIT function. To join it to your data, you'll want to use CROSS APPLY.
create table #a (
id int identity(1,1),
email varchar(max)
)
insert #a
values ('cesarcastillo88#hotmail.com ; laura23#gmail.com ; test#compliance.com')
, ('dannyboy#irish.com')
select id
, email
, substring(email, CHARINDEX('#', email) + 1, len(email)) as domain
from #a
select a.id
, substring(ltrim(rtrim(b.value)), CHARINDEX('#', ltrim(rtrim(b.value))) + 1, len(ltrim(rtrim(b.value)))) as domain
from #a a
cross apply string_split(email, ';') b
drop table #a

deleting second comma in data

Ok so I have a table called PEOPLE that has a name column. In the name column is a name, but its totally a mess. For some reason its not listed such as last, first middle. It's sitting like last,first,middle and last first (and middle if there) are separated by a comma.. two commas if the person has a middle name.
example:
smith,steve
smith,steve,j
smith,ryan,tom
I'd like the second comma taken away (for parsing reason ) spaces put after existing first comma so the above would come out looking like:
smith, steve
smith, steve j
smith, ryan tom
Ultimately I'd like to be able to parse the names into first, middle, and last name fields, but that's for another post :_0. I appreciate any help.
thank you.
Drop table T1;
Create table T1(Name varchar(100));
Insert T1 Values
('smith,steve'),
('smith,steve,j'),
('smith,ryan,tom');
UPDATE T1
SET Name=
CASE CHARINDEX(',',name, CHARINDEX(',',name)+1) WHEN
0 THEN Name
ELSE
LEFT(name,CHARINDEX(',',name, CHARINDEX(',',name)+1)-1)+' ' +
RIGHT(name,LEN(Name)-CHARINDEX(',',name, CHARINDEX(',',name)+1))
END
Select * from T1
This seems to work. Not the most concise but avoids cursors.
DECLARE #people TABLE (name varchar(50))
INSERT INTO #people
SELECT 'smith,steve'
UNION
SELECT 'smith,steve,j'
UNION
SELECT 'smith,ryan,tom'
UNION
SELECT 'commaless'
SELECT name,
CASE
WHEN CHARINDEX(',',name) > 0 THEN
CASE
WHEN CHARINDEX(',',name,CHARINDEX(',',name) + 1) > 0 THEN
STUFF(STUFF(name, CHARINDEX(',',name,CHARINDEX(',',name) + 1), 1, ' '),CHARINDEX(',',name),1,', ')
ELSE
STUFF(name,CHARINDEX(',',name),1,', ')
END
ELSE name
END AS name2
FROM #people
Using a table function to split apart the names with a delimiter and for XML Path to stitch them back together, we can get what you're looking for! Hope this helps!
Declare #People table(FullName varchar(200))
Insert Into #People Values ('smith,steve')
Insert Into #People Values ('smith,steve,j')
Insert Into #People Values ('smith,ryan,tom')
Insert Into #People Values ('smith,john,joseph Jr')
Select p.*,stuff(fn.FullName,1,2,'') as ModifiedFullName
From #People p
Cross Apply (
select
Case When np.posID<=2 Then ', ' Else ' ' End+np.Val
From #People n
Cross Apply Custom.SplitValues(n.FullName,',') np
Where n.FullName=p.FullName
For XML Path('')
) fn(FullName)
Output:
ModifiedFullName
smith, steve
smith, steve j
smith, ryan tom
smith, john joseph Jr
SplitValues table function definition:
/*
This Function takes a delimited list of values and returns a table containing
each individual value and its position.
*/
CREATE FUNCTION [Custom].[SplitValues]
(
#List varchar(max)
, #Delimiter varchar(1)
)
RETURNS
#ValuesTable table
(
posID int
,val varchar(1000)
)
AS
BEGIN
WITH Cte AS
(
SELECT CAST('<v>' + REPLACE(#List, #Delimiter, '</v><v>') + '</v>' AS XML) AS val
)
INSERT #ValuesTable (posID,val)
SELECT row_number() over(Order By x) as posID, RTRIM(LTRIM(Split.x.value('.', 'VARCHAR(1000)'))) AS val
FROM Cte
CROSS APPLY val.nodes('/v') Split(x)
RETURN
END
GO
String manipulation in SQLServer, outside of writing your own User Defined Function, is limited but you can use the PARSENAME function for your purposes here. It takes a string, splits it on the period character, and returns the segment you specify.
Try this:
DECLARE #name VARCHAR(100) = 'smith,ryan,tom'
SELECT REVERSE(PARSENAME(REPLACE(REVERSE(#name), ',', '.'), 1)) + ', ' +
REVERSE(PARSENAME(REPLACE(REVERSE(#name), ',', '.'), 2)) +
COALESCE(' ' + REVERSE(PARSENAME(REPLACE(REVERSE(#name), ',', '.'), 3)), '')
Result: smith, ryan tom
If you set #name to 'smith,steve' instead, you'll get:
Result: smith, steve
Segment 1 actually gives you the last segment, segment 2 the second to last etc. Hence I've used REVERSE to get the order you want. In the case of 'steve,smith', segment 3 will be null, hence the COALESCE to add an empty string if that is the case. The REPLACE of course changes the commas to periods so that the split will work.
Note that this is a bit of a hack. PARSENAME will not work if there are more than four parts and this will fail if the name happens to contain a period. However if your data conforms to these limitations, hopefully it provides you with a solution.
Caveat: it sounds like your data may be inconsistently formatted. In that case, applying any automated treatment to it is going to be risky. However, you could try:
UPDATE people SET name = REPLACE(name, ',', ' ')
UPDATE people SET name = LEFT(name, CHARINDEX(' ', name)-1)+ ', '
+ RIGHT(name, LEN(name) - CHARINDEX(' ', name)
That'll work for the three examples you give. What it will do to the rest of your set is another question.
Here's an example with CHARINDEX() and SUBSTRING
WITH yourTable
AS
(
SELECT names
FROM
(
VALUES ('smith,steve'),('smith,steve,j'),('smith,ryan,tom')
) A(names)
)
SELECT names AS old,
CASE
WHEN comma > 0
THEN SUBSTRING(spaced_names,0,comma + 1) --before the comma
+ SUBSTRING(spaced_names,comma + 2,1000) --after the comma
ELSE spaced_names
END AS new
FROM yourTable
CROSS APPLY(SELECT CHARINDEX(',',names,CHARINDEX(',',names) + 1),REPLACE(names,',',', ')) AS CA(comma,spaced_names)

case statement to delete extra spaces only when there is some

I replace all blanks with # using this
SELECT *, REPLACE(NAME,' ','#') AS NAME2
which results miss#test#blogs############## (different number of #s dependent on length of name!
I then delete all # signs after the name using this
select *, substring(Name2,0,charindex('##',Name2)) as name3
which then gives my desired results of, for example MISS#test#blogs
However some wheren't giving this result, they are null. This is because annoyingly some rows in the sheet I have read in dont have the spaces after the name.
is there a case statement i can use so it only deletes # signs after the name if they are there in the first place?
Thanks
The function rtrim can be used to remove trailing spaces. For example:
select replace(rtrim('miss test blogs '),' ','#')
-->
'miss#test#blogs'
Example at SQL Fiddle.
try this:
Declare #t table (name varchar(100),title varchar(100),forename varchar(100))
insert into #t
values('a b c','dasdh dsalkdk asdhl','asd dfg sd')
SELECT REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(name)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS Name,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(title)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS title,
REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(forename)),' ',' '+CHAR(7)),CHAR(7)+' ','') ,CHAR(7),'') AS forename
FROM #t WHERE
(CHARINDEX(' ',NAME) > 0 or CHARINDEX(' ',title) > 0 or CHARINDEX(' ',forename) > 0)
SQL Fiddle Demo
select name2, left(name2,len(name2)+1-patindex('%[^#]%',reverse(name2)+'.'))
from (
SELECT *, REPLACE(NAME,' ','#') AS NAME2
from t
) x;
Check this SQL Fiddle
For posterity, sample table:
create table t (name varchar(100));
insert t select 'name#name#ne###'
union all select '#name#name'
union all select 'name name hi '
union all select 'joe public'
union all select ''
union all select 'joe'
union all select 'joe '
union all select null
union all select ' leading spaces'
union all select ' leading trailing ';
Don't quite understand the question, but if the problem is there is not spaces after some names, can't you do this first:
SELECT *, REPLACE(NAME+' ',' ','#') AS NAME2
i.e., add a space to all names right off the bat?
I had this same problem some days ago.
Well actually, there's a quickly way to subtract the spaces from both the begin and end inside strings. In SQL Server, you can use the RTRIM and LTRIM for this. The first one supresses spaces from right side and the second supresses from left. But, if in your scenario also may exists more than one space in the middle of the string I sugest you take a look on this post on SQL Server Central: http://www.sqlservercentral.com/articles/T-SQL/68378/
There the script's author explain, in details, a good solution for this situation.

eliminate first numeric from string

I have the data in column like this 12 address, i want to eliminate numeric with address how can i do to achieve the result Address. Here can be any other string also not only address.
Query:
SELECT Address FROM TABLE
Thanks
In SQL Server:
SELECT
COALESCE(LTRIM(SUBSTRING(Address, FirstPos, 2147483647)), '') AS Address
FROM (
SELECT
Address,
NULLIF(PATINDEX('%[^0-9]%', Address), 0) AS FirstPos
FROM atable
) s
SELECT SUBSTRING(address, CHARINDEX(' ',address)+1,field_len)
FROM table
Explained
Syntax: SUBSTRING(fieldname, start_position, end_position)
In your case
SUBSTRING(
address -- your field name
, CHARINDEX(' ',address)+1 -- find the space char
, field_len -- get all the rest of the string
)
SELECT RIGHT(Address,LEN(Address) - CHARINDEX (' ', Address) + 1) FROM tbl
Something like this should work.