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

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.

Related

Split name into multiple parts in SELECT statement

I cannot seem to find an existing post on splitting a string into the parts I require. I have a database field in SQL Server that contains the "LastName FirstName MI" (no commas just spaces delimiting each part of a person's name). I have the following SQL to get the FirstName and Last, but cannot figure out how to get the Middle Initial or Middle Name.
Ex. Doe John B
SELECT
RTRIM(LEFT([PATIENT_NAME], CHARINDEX(' ', [PATIENT_NAME]))) AS LastName,
SUBSTRING([PATIENT_NAME], CHARINDEX(' ', [PATIENT_NAME]) + 1, LEN([PATIENT_NAME])) AS FirstName
FROM
Clients
Results in:
FirstName = John B
LastName = Doe
How to just return the first name without the middle initial and get the 'B' as middle name from this string in this SELECT statement?
You can either take the right 1 character, or reverse the string the take the first char.
SELECT RIGHT(LTRIM(RTRIM([Patient_Name])), 1) AS Middle_Initial
SELECT LEFT(REVERSE(LTRIM(RTRIM([Patient_Name]))), 1) AS Middle_Initial
As for removing MI from your firstname string, I would either find the length of the string and take the left N-2 chars or I would charindex the space and then take that many chars. To put it all together:
DECLARE #name VARCHAR(100) = 'Smith David M '
--Clean the string of leading/trailing whitespace
SELECT LTRIM(RTRIM(#name)) AS name_cleaned
--Find the first space to parse out the last name
SELECT CHARINDEX(' ', #name) AS first_space
--Select all chars before the first space
SELECT LEFT(LTRIM(RTRIM(#name)), CHARINDEX(' ', #name)-1) AS last_name
--Find the next space, use the starting location as the previous space and add 1
SELECT CHARINDEX(' ', #name, 7) AS second_space
--Select all chars between the spaces
SELECT SUBSTRING(#name, CHARINDEX(' ', #name)+1, CHARINDEX(' ', #name, 7) - CHARINDEX(' ', #name)) AS first_name
--Select the right most char for middle initial
SELECT RIGHT(LTRIM(RTRIM(#name)), 1) AS middle
You can REPLACE the space characters with period characters (.) and use PARSENAME().
Note that this would work for all 3 parts of the name, not just the middle initial.
When using the CHARINDEX on the last name, you'll use it as the length of the substring. Then, on the FirstName, use it again as start position on the substring. Now, the trick on the Middle, on the CHARINDEX, you have to include the start position which will be the LEN minus the LastName CHARINDEX. this would gives you the second space which is the position you want to start with for taking the Middle Name.
See the example below :
DECLARE #tb TABLE (PATIENT_NAME varchar(250));
INSERT INTO #tb VALUES
('Doe John B')
DECLARE
#LastName INT
, #Middle INT
SELECT
#LastName = CHARINDEX(' ', PATIENT_NAME)
, #Middle = CHARINDEX(' ', PATIENT_NAME, LEN(PATIENT_NAME) - CHARINDEX(' ', PATIENT_NAME))
FROM #tb
SELECT
SUBSTRING(PATIENT_NAME, 1, #LastName) LastName
, SUBSTRING(PATIENT_NAME, #LastName, LEN(PATIENT_NAME) - #LastName) FirstName
, SUBSTRING(PATIENT_NAME, #Middle, LEN(PATIENT_NAME) - #Middle + 1 ) Middle
FROM #tb
I have declared some variables to make things much readable, but you can do it without them.
Surely, LEFT and RIGHT are the easier approaches on taking the lastname and Middle Name. Along with using some helper functions such as REVERSE and TRIM, but I would prefer PARSENAME as a simpler and cleaner approach.
Here is an example :
SELECT
PARSENAME(REPLACE(PATIENT_NAME,' ','.'),3) LastName
, PARSENAME(REPLACE(PATIENT_NAME,' ','.'),2) FirstName
, PARSENAME(REPLACE(PATIENT_NAME,' ','.'),1) Middle
Since the number of elements you must extract from your string is fixed(3) you can use XML based split:
DECLARE #clients TABLE (PATIENT_NAME nvarchar(max));
INSERT INTO #clients VALUES
(' Doe John B ')
,(' Doe Jane C ')
,(' Doe Jill ')
;WITH Splitted
AS (
SELECT PATIENT_NAME as ORIGINAL_PATIENT_NAME
,REPLACE(REPLACE(REPLACE(ltrim(rtrim(PATIENT_NAME)),' ','<>'),'><',''),'<>',' ') as PATIENT_NAME
,CAST('<x>' + REPLACE(REPLACE(REPLACE(REPLACE(ltrim(rtrim(PATIENT_NAME)),' ','<>'),'><',''),'<>',' '), ' ', '</x><x>') + '</x>' AS XML) AS Parts
FROM #clients
)
SELECT
ORIGINAL_PATIENT_NAME
,PATIENT_NAME
,Parts.value(N'/x[1]', 'nvarchar(max)') AS LAST_NAME
,Parts.value(N'/x[2]', 'nvarchar(max)') AS FIRST_NAME
,Parts.value(N'/x[3]', 'nvarchar(max)') AS MIDDLE_NAME
FROM Splitted
Results:
As you can see it works even with random-spaced names.

How to get middle portion from Sql server table data?

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

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

Data is "lastName, FirstName". I need to write it as "FirstName LastName"

Running sql server 2008 The title says it, but in my select statement I have this
COALESCE( ca.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)')
,ca2.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)'))
AS IR_Name
and it returns lastName, FirstName
This becomes a problem when exporting to a csv as it creates two separate columns and what not.
I somehow have to figure out how to have the string be firstName lastName, no commas, and putting the firstName first.
SELECT PARSENAME(REPLACE('John , Doe', ',', '.'), 1) + ' ' + PARSENAME(REPLACE('John , Doe', ',', '.'), 2)
this will switch 'John , Doe' to 'Doe John'. Now, you just need replace the 'John, Doe" with the
COALESCE(ca.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)'),ca2.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)')) AS IR_Name
Another way to do this is by using string functions:
select (case when IR_Name like '%,%'
then (ltrim(rtrim(substring(IR_NAME, charindex(',', IR_NAME)+1, 1000))) + ' ' +
ltrim(rtrim(left(IR_Name, charindex(',', IR_NAME) - 1)))
)
else IR_NAME
end) t
from (select COALESCE( ca.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)')
,ca2.AttributeList.value('(/AttributeList/IRName)[1]','varchar(max)'))
AS IR_Name
. . .
) t
The trimming functions are to remove extra spaces.
The parsename solution is clever. But, it looks strange since parsename is designed for multipart naming conventions, with up to four parts separated by periods.

set column value to part of a string in another column

i have a table with a column named CustomerName which stores a customer's full name(thats both names of a customer - first name, last name and any other names).
I want to redesign this table such that instead of just having CustomerName field, i should have CustomerFirstName, CustomerLastName and CustomerOtherNames(then customerName can be a concatenation of the 3 fields).
i already have customer records in the table with CustomerNames in format below
CustomerName
Tom John
Mary Joy
San Roy
now i need to run an update query that will set Tom, Mary and San as CustomerFirstName and set John, Joy and Roy as CustomerLastName for their respective rows but am stuck on this.
The following integrates the formulas suggested by Matt (Lima) into the actual UPDATE query; it also deals with various cases such as
when there is only a FirstName,
when there are leading or trailing spaces
when there's more than one space separating first name from last name
Alternatively, one may do away with the extra tests aimed at ensuring that there is a space, by adding a WHERE clause (WHERE CustomerName like ('% %').
-- Ensure no leading nor trailing spaces
UPDATE myTable
SET CustomerName = TRIM(CustomerName)
UPDATE myTable
SET FirstName = TRIM(LEFT(TRIM(CustomerName),
CASE CHARINDEX(' ', CustomerName)
WHEN 0 THEN LEN(CustomerName)
ELSE CHARINDEX(' ', CustomerName) -1
END)),
LastName = CASE CHARINDEX(' ', CustomerName)
WHEN 0 THEN ''
ELSE TRIM(SUBSTRING(CustomerName, CHARINDEX(' ', CustomerName) + 1, LEN(CustomerName))
END
You might be able to use something like:
SELECT SUBSTRING(CustomerName, 1, CHARINDEX(' ', CustomerName) - 1) AS [FirstName],
SUBSTRING(CustomerName, CHARINDEX(' ', CustomerName) + 1, LEN(CustomerName)) AS [LastName]
FROM yourTableName
I got this solution from: http://www.sql-server-helper.com/tips/split-name.aspx
Hope this helps.
Matt
Try something like:
SELECT SUBSTR(CustomerName, 1 ,INSTR(CustomerName, ' ', 1, 1)-1) as first_name, SUBSTR(CustomerName, INSTR(CustomerName,' ',1,1)) as last_name from yourTableName
(oracle)