How to get middle portion from Sql server table data? - sql

I am trying to get First name from employee table, in employee table full_name is like this: Dow, Mike P.
I tried with to get first name using below syntax but it comes with Middle initial - how to remove middle initial from first name if any. because not all name contain middle initial value.
-- query--
select Employee_First_Name as full_name,
SUBSTRING(
Employee_First_Name,
CHARINDEX(',', Employee_First_Name) + 1,
len(Employee_First_Name)) AS FirstName
---> remove middle initial from right side from employee
-- result
Full_name Firstname Dow,Mike P. Mike P.
--few example for Full_name data---
smith,joe j. --->joe (need result as)
smith,alan ---->alan (need result as)

Instead of specifying the len you need to use charindex again, but specify that you want the second occurrence of a space.
select Employee_First_Name as full_name,
SUBSTRING(
Employee_First_Name,
CHARINDEX(',', Employee_First_Name) + 1,
CHARINDEX(' ', Employee_First_Name, 2)) AS FirstName
One thing to note, the second charindex can return 0 if there is no second occurence. In that case, you would want to use something like the following:
select Employee_First_Name as full_name,
SUBSTRING(
Employee_First_Name,
CHARINDEX(',', Employee_First_Name) + 1,
IIF(CHARINDEX(' ', Employee_First_Name, 2) = 0, Len(Employee_First_name), CHARINDEX(' ', Employee_First_Name, 2))) AS FirstName

This removes the portion before the comma.. then uses that string and removes everything after space.
WITH cte AS (
SELECT *
FROM (VALUES('smith,joe j.'),('smith,alan'),('joe smith')) t(fullname)
)
SELECT
SUBSTRING(
LTRIM(SUBSTRING(fullname,CHARINDEX(',',fullname) + 1,LEN(fullname))),
0,
COALESCE(NULLIF(CHARINDEX(' ',LTRIM(SUBSTRING(fullname,CHARINDEX(',',fullname) + 1,LEN(fullname)))),0),LEN(fullname)))
FROM cte
output
------
joe
alan
joe

To be honest, this is most easily expressed using multiple levels of logic. One way is using outer apply:
select ttt.firstname
from t outer apply
(select substring(t.full_name, charindex(', ', t.full_name) + 2, len(t.full_name) as firstmi
) tt outer apply
(select (case when tt.firstmi like '% %'
then left(tt.firstmi, charindex(' ', tt.firstmi)
else tt.firstmi
end) as firstname
) as ttt
If you want to put this all in one complicated statement, I would suggest a computed column:
alter table t
add firstname as (stuff((case when full_name like '%, % %.',
then left(full_name,
charindex(' ', full_name, charindex(', ', full_name) + 2)
)
else full_name
end),
1,
charindex(', ', full_name) + 2,
'')

If format of this full_name field is the same for all rows, you may utilize power of SQL FTS word breaker for this task:
SELECT N'Dow, Mike P.' AS full_name INTO #t
SELECT display_term FROM #t
CROSS APPLY sys.dm_fts_parser(N'"' + full_name + N'"', 1033, NULL, 1) p
WHERE occurrence = 2
DROP TABLE #t

Related

Separate fullname into first and last, and remove 'junk'

Wasn't sure of the best way to word this. So I have a column with names, as below:
SalesPerson_Name
----------------
Undefined - 0
Sam Brett-sbrett
Kelly Roberts-kroberts
Michael Paramore-mparamore
Alivia Lawler-alawler
Ryan Hooker-rhooker
Heather Alford-halford
Cassandra Blegen-cblegen
JD Holland-jholland
Vendor Accounts-VENDOR
Other Accounts-OTHER
Getting the names separated is easy enough with PARSENAME and REPLACE functions, but where I'm running into a pickle is with getting rid of the 'junk' at the end:
SELECT SalesPerson_Key
,SalesPerson_Name
,CASE
WHEN PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 2) IS NULL
THEN PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 1)
ELSE PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 2)
END AS FirstName
,CASE
WHEN PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 2) IS NULL
THEN NULL
ELSE PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 1)
END AS LastName
FROM Salesperson
RESULTS FOR LASTNAME COLUMN:
LastName
--------
0
Brett-sbrett
Roberts-kroberts
Paramore-mparamore
Lawler-alawler
Hooker-rhooker
Alford-halford
Blegen-cblegen
Holland-jholland
Accounts-VENDOR
Accounts-OTHER
Specifically, I want to get rid of the text (userid) at the end of the last name. If the names were the same length, I could just use a RIGHT function, but they vary in length. Ideas?
select left(PARSENAME(REPLACE(SalesPerson_Name, ' ', '.'), 1), len(SalesPerson_Name)-CHARINDEX('-',SalesPerson_Name)-1)
You are getting charindex of - and taking the left string of it.
If you just want to remove the last word (username) you can use a query like this
select
rtrim(
substring(
SalesPerson_Name,
1,
charindex('-',SalesPerson_Name,1)-1
)
)
from Salesperson
The charindex function locates the occurrence of the character/s you are looking for.
Consider whether hyphen is followed by a space or not, and split depending on these two cases
with Salesperson( SalesPerson_Name ) as
(
select 'Undefined - 0' union all
select 'Sam Brett-sbrett' union all
select 'Kelly Roberts-kroberts' union all
select 'Michael Paramore-mparamore' union all
select 'Alivia Lawler-alawler'
)
select case when substring(SalesPerson_Name,charindex(' ',SalesPerson_Name)+1,1) = '-' then
substring(SalesPerson_Name,charindex(' ',SalesPerson_Name)+3,len(SalesPerson_Name))
else
substring(SalesPerson_Name,charindex(' ',SalesPerson_Name)+1,len(SalesPerson_Name))
end as last_name
from Salesperson s;
last_name
------------------
0
Brett-sbrett
Roberts-kroberts
Paramore-mparamore
Lawler-alawler

SQL - re.split: BY comma THEN space

I want to split the following string into City, Province, Postal Code.
Thank you so much for the help!!!!
Description: Split by comma, then split by space only once.
A = 'Vaughan, ON L6D 9X0'
Result:
(Vaughan, ON, L6D9X0)
Attempt:
re.split(',|/s[1]', A)
Try This,
This selected the values into rows, maybe you can pivot the cte C2 same in order to get it as columns
WITH CTE
AS
(
SELECT
1 Seq,
'Vaughan, ON L6D 9X0' "Txt"
UNION ALL
SELECT
Seq+1 "Seq",
Txt = CASE WHEN Txt LIKE '% %'
THEN LTRIM(RTRIM(SUBSTRING(Txt,CHARINDEX(' ',Txt),LEN(Txt))))
ELSE NULL END
FROM CTE
WHERE ISNULL(txt,'')<>''
),C2
AS
(
SELECT
CASE Seq
WHEN 1 THEN 'City'
WHEN 2 THEN 'Province'
ELSE 'PostalCode' END "Head",
CASE Seq
WHEN 1
THEN SUBSTRING(Txt,1,CHARINDEX(',',Txt)-1)
WHEN 2
THEN SUBSTRING(Txt,1,CHARINDEX(' ',Txt)-1)
ELSE Txt END "Txt"
FROM CTE
WHERE Seq<4
)
SELECT
*
FROM C2;
If you have multiple rows that need to be parsed in the same way then, you can give the same in the select statement of 1st CTE and in that case, the logic for Seq on the first select might need to be changed. As per the above, the output will be as follows
With Postgres you can do that using:
select split_part(a, ',', 1) as city,
left(trim(split_part(a,',',2)), strpos(trim(split_part(a,',',2)), ' ')),
substr(trim(split_part(a,',',2)) as province, strpos(trim(split_part(a,',',2)), ' ') + 1) as postal_code
from the_table;
This can be made a bit more readable by using a derived table:
select city,
left(second_part, strpos(second_part, ' ')) as province,
substr(second_part, strpos(second_part, ' ') + 1) as postal_code
from (
select split_part(a, ',', 1) as city,
trim(split_part(a, ',', 2)) as second_part
from the_table
) t
IF, You are working with Microsoft SQL Server, then you could use SUBSTRING() &CHARINDEX() function to find specific Char index to split the string values.
SELECT SUBSTRING(<column>, 1, CHARINDEX(',', <column>)-1) City,
SUBSTRING(SUBSTRING(<column>, CHARINDEX(' ', <column>)+1, LEN(<column>)), 1, CHARINDEX(' ', SUBSTRING(<column>, CHARINDEX(' ', <column>)+1, LEN(<column>)))) Province,
SUBSTRING(SUBSTRING(<column>, CHARINDEX(' ', <column>)+1, LEN(<column>)), CHARINDEX(' ', SUBSTRING(<column>, CHARINDEX(' ', <column>)+1, LEN(<column>)))+1, LEN(<column>)) [Postal Code];
Desired Output :
City Province Postal Code
Vaughan ON L6D 9X0

How to find second value inside a column

How do I list the names of all band members with the same last name?
The column has values like this
band_NAME
-------------------
Carla Thomas
Stephen E. Rice
Cynthia P. Tree
Richard Anthony Paul
Ann Frances Smith
Lorace Black
Timothy Adam Paul
I know we would have to use instr and substr. I just don't get how we would determine the position.
I know the basic format is going to be like
SELECT band_NAME
FROM TABLE
where substr(band_name, ?, instr( ) IN
(select substr(band_name, ?, instr( )-1)
from table
group by SUBSTR(band_NAME , ?, INSTR( )-1 )
HAVING COUNT(* ) > 1 );
But what goes in the question marks and inside the instr?
Would appreciate any help on this!
I'm assuming that your delimiter between first and last name is a single space. More spaces in the string are a part of last name. Thus, you probably want to search for the first space character.
Return position of the first occurence of substring with instr(str, substr).
Then, use substring(str, pos) to return the substring starting at a given position (feed by instr function).
SELECT substring(band_name, instr(band_name, ' '))
FROM yourtable
Try this:
SELECT t1.band_NAME
FROM TABLE t1 LEFT JOIN TABLE t2
ON SUBSTRING_INDEX(t1.band_name, ' ', - 1) = SUBSTRING_INDEX(t2.band_name, ' ', - 1)
WHERE t1.band_name <> t2.band_name
And this like your pseudocode MySQL:
SELECT band_NAME FROM TABLE
Where FIND_IN_SET (SUBSTRING_INDEX(band_name, ' ', -1),
(Select SUBSTRING_INDEX(band_name, ' ', -1) bn
From TABLE Group by bn
having Count(bn) > 1
)
)
SQL Server
SELECT band_NAME FROM TABLE
Where
SUBSTRING(band_NAME, CHARINDEX(' ', band_NAME) + 1, LEN(band_NAME)) AS [Last Name]
IN
(Select SUBSTRING(band_NAME, CHARINDEX(' ', band_NAME) + 1, LEN(band_NAME)) AS [Last Name]
From TABLE Group by [Last Name] -- or SUBSTRING(band_NAME, CHARINDEX(' ', band_NAME) + 1, LEN(band_NAME)) AS [Last Name]
having Count(*) > 1
)
)
Additionally I thinks you can benefit from STRING_SPLIT in some way
Try This
with cte as
(
select band_name, ROW_NUMBER() over(partition by SUBSTRING(band_name,CHARINDEX(' ',band_name),LEN(band_name)) order by band_name) as cnt,
SUBSTRING(band_name,CHARINDEX(' ',band_name),LEN(band_name)) as lastname
from your_table
)
select band_name
from cte
where lastname in (select lastname from cte where cnt > 1)
okay,
The best solution is to change your schema and store last name in a separate column.
In the mean time you could get the last name like this,
SELECT
[band_NAME],
CASE WHEN CHARINDEX(' ', [band_NAME]) > 0
THEN
RIGHT([band_NAME], CHARINDEX(' ', REVERSE([band_NAME])))
ELSE
[band_NAME]
END [LastName]
FROM
[TABLE]
You could then group them like this
SELECT
[LastName],
COUNT(*)
FROM
(
SELECT
[band_NAME],
CASE WHEN CHARINDEX(' ', [band_NAME]) > 0
THEN
RIGHT([band_NAME], CHARINDEX(' ', REVERSE([band_NAME])))
ELSE
[band_NAME]
END [LastName]
FROM
[TABLE]
) [TABLEWithLastName]
GROUP BY
[LastName];

How to format the order of first/last name and remove prefix and nickname

I have a need to retrieve a hierarchy of managers and the column which stores the manager names for a given person are formatted like this Smith, Mr. William (Bill). I want this output to simply be William Smith. So far I have put this together:
SELECT DISTINCT RIGHT(u.manager, LEN(u.manager)-(1+CHARINDEX(', ', u.manager))) + ' ' +
LEFT(u.manager, CHARINDEX(', ', u.manager) - 1) as ManagerName
FROM Users u
The current result from that query using my example above is Mr. William (Bill) Smith. This CHARINDEX and SUBSTRING stuff always gives me a lot of trouble so I am not really sure what the easiest way to do this is. This is also a one-off, so I am not sure a function would be useful here.
DEMO
SELECT
SUBSTRING(manager,0,CHARINDEX(',', manager)) as surname,
SUBSTRING(manager,CHARINDEX('. ', manager)+2, LEN(manager)-CHARINDEX(' (', manager)+1) as name,
CONCAT(SUBSTRING(manager,CHARINDEX('. ', manager)+2, LEN(manager)-CHARINDEX(' (', manager)+1),
' ',
SUBSTRING(manager,0,CHARINDEX(',', manager))) as 'name surname'
FROM
Users
Result:
+-------------+-----------+--------------+
| surname | name | name surname |
+-------------+-----------+--------------+
Smith William William Smith
I took your query and modified a little bit:
SELECT
---this is the tricky part: inner part finds the first instance of '(' parenthesis
--and substract it from the length of the first name and get only the left part of the first name by subtracting it
CONCAT (
LEFT(t.FirstName, LEN(t.FirstName) - (LEN(t.FirstName) - CHARINDEX('(', t.FirstName) + 1))
,t.LastName
)
FROM (
--basically separating your above syntax to two columns
SELECT RIGHT('Smith, Mr. William (Bill)', LEN('Smith, Mr. William (Bill)') - CHARINDEX('.', 'Smith, Mr. William (Bill)') - 1) AS FirstName
,LEFT('Smith, Mr. William (Bill)', CHARINDEX(', ', 'Smith, Mr. William (Bill)') - 1) AS LastName
) t
Here is the query that should work with your table name and column:
SELECT
---Use case when statement to determine if there are any instances of '(' in the first name
CONCAT (
CASE
WHEN CHARINDEX('(', t.FirstName) > 0
THEN LEFT(t.FirstName, LEN(t.FirstName) - (LEN(t.FirstName) - CHARINDEX('(', t.FirstName) + 1))
ELSE t.FirstName + ' '
END
,t.LastName
)
FROM (
SELECT
RIGHT(u.manager, LEN(u.manager) - CHARINDEX('.', u.manager) - 1) AS FirstName
,LEFT(u.manager, CHARINDEX(', ', u.manager) - 1) AS LastName from Users u
) t
SELECT RIGHT(NameStripped, LEN(NameStripped) - (1 + CHARINDEX(', ', NameStripped))) + ' ' + LEFT(NameStripped, CHARINDEX(', ', NameStripped) - 1) AS ManagerName --Your original code
FROM (
SELECT replace(replace(
LEFT(u.manager, CHARINDEX('(', u.manager) - 2) --Get rid of nickname
, 'Mr. ', ''), 'Ms.', '') AS NameStripped --Get rid of Mr/Ms
from MyTable u) a
This should work - I used the code you posted, but added a subquery to remove the nicknames and prefixes.
Note that you may need to adjust this if a) you have more prefix options than this (in which case you could add additional replaces) and/or b) not everyone in your database has a nickname (in which case you'll want to wrap that part in a case statement, most likely).

SQL- Get the substring after first space and second space in separate columns

I have a column as FullName containg FirstName, MiddleName, LastName in it.
For example:
FullName: Marilyn Kean Kirkland
I want to have 3 separate columns for FirstName, MiddleName and LastName from the FullName by taking a substring from it.
I am pulling the FirstName by using the code:
substring(c.LegalName, 1, CHARINDEX(' ', c.LegalName)) as 'First Name'
I am wondering how can I pull just the middle name which comes after first space and before second space?
Also, I want to pull the last name which comes after the second space?
SQL Server doesn't have very good string manipulation functions. This is easier with subqueries:
select firstname,
stuff(reverse(stuff(reverse(legalname), 1, len(lastname) + 1, '')),
1, len(firstname) + 1, '')
from (select legalname,
left(legalname, charindex(' ', legalname) - 1) as firstname,
right(legalname, charindex(' ', reverse(legalname)) - 1) as lastname
. . .
) c
However, I would be very careful, because not all people have three part names. And others have suffixes (JR, SR) and other complications.
You can try something like this.
;WITH c AS
(
SELECT 'Marilyn Kean Kirkland' AS legalname
UNION ALL SELECT 'J Smith' AS legalname
)
SELECT
SUBSTRING(legalname,1,space1) firstname,
SUBSTRING(legalname,space1,space2 - space1 + 1) middlename,
SUBSTRING(legalname,space2 + 1,totallength - space2) lastname
FROM
(
SELECT
legalname,
CHARINDEX(' ',legalname) space1,
LEN(legalname) - CHARINDEX(' ',REVERSE(legalname)) space2,
LEN(legalname) as totallength
FROM c
)c
GO
As noted above by other users as well,these scripts will work with user that only have 3 part or 2 part names.