Extract surname with initial in SQL Server - sql-server-2008

In SQL Server, I have a column NAME with data like this:
1, CHAN Tai Man
2, CHAN Ting Ting
I would like to have a query that extract the NAME2 to
1, CHAN T M
2, CHAN T T
As you may observe that only initial of the given name is required. How can I achieve that in SQL Server 2008? Many thanks for your gentle help.

Like Gordon said,the first one is easy and here's my take on it
DECLARE #table TABLE(id INT,name nvarchar(50))
Insert into #table
Values(1,'CHAN Tai Man')
Insert into #table
Values(2, 'CHAN Ting Ting')
select name
, LEFT(name, (PATINDEX('%[ _-]%',name))) +substring(name,(PATINDEX('%[ _-]%',name)+1),1) +' '+substring(reverse(rtrim(substring(reverse(name), 1, charindex(' ', reverse(name))))),(PATINDEX('%[ _-]%',reverse(rtrim(substring(reverse(name), 1, charindex(' ', reverse(name))))))+1),1) as Fullname
from #table

The first initial is pretty easy:
select left(name, charindex(' ', name) + 1)
The second is a bit tougher. I think the logic is like this
select (left(name, charindex(' ', name) + 1) +
substring(reverse(name), charindex(' ', reverse(name)) - 1, 1)
)
You might need to include case statements to be sure that the name has two spaces.

Related

Extracting second word from each row in a column

I have a vendors table in my database that am experimenting with, as shown below
And when i run the sql command below
SELECT vendor_name
FROM vendors
ORDER BY vendor_name
LIMIT 10
I get the output below
My issue is am trying to extract the second word from each vendor_name and when the second word doesn't exist it's supposed to return a blank cell.
And below is the sql query i have written to do just that
SELECT vendor_name,
SUBSTRING(
SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1),
1,
LOCATE( ' ', SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1) ) - 1
) AS second_word
FROM vendors
ORDER BY vendor_name
LIMIT 10
And here is the output of that sql query
If you notice from the output above, when the words in the vendor_name are more than two, it returns the second word just fine and when the vendor_name contains one word it returns a blank cell as expected.
Problem comes when the vendor_name contains exactly two words, instead of returning the second word it is returning a blank cell for example in the case of American Express and ASC Signs.
How can i better improve my query so that even when the vendor_name does contain two words, it does return the second word instead of a blank cell?
Thank you.
That's because there is no space after the second word, if the text ends there, the locate() has no space to find.
Quick hack: Add a space at the end.
LOCATE( ' ', CONCAT(SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1), ' ') ) - 1
SELECT vendor_name , substr(vendor_name , instr(vendor_name, " ") ,
case when LOCATE (' ', vendor_name,instr(vendor_name, " ") ) > 0 then LOCATE (' ',
vendor_name,instr(vendor_name, " ") ) else CHAR_LENGTH (vendor_name) end )
from vendors ;
I took tips from both #stick bit and #kiran gadhe and i came up with this sql query and it's working just fine
SELECT vendor_name,
CASE
WHEN INSTR( vendor_name, ' ' ) = 0
THEN
''
ELSE
SUBSTRING(
SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1),
1,
LOCATE( ' ', CONCAT(SUBSTRING( vendor_name, LOCATE(' ', vendor_name) + 1), ' ') ) - 1
)
END AS second_word
FROM vendors
ORDER BY vendor_name
LIMIT 10

breaking columns using substring

i am having long string in column as a full name of the employee , i want to break that down in first name, middle name and last name. for example i am having Andrade, Maria Sandra (lname,(space)fname(space)mname)breaking will be like
fname =Maria, lname= Andrade and middle name like Sandra.
My column generally have lname,fname.
i am able to divide lname, but not correct breaking for fname and mname
SELECT EmployeeName as [full name ], SUBSTRING( EmployeeName,CHARINDEX(',',EmployeeName)+1,LEN(EmployeeName)) as[First name ]
,SUBSTRING( EmployeeName,0,CHARINDEX(',',EmployeeName)) [Last Name]
, SUBSTRING( SUBSTRING( EmployeeName,CHARINDEX(',',EmployeeName)+1,LEN(EmployeeName)),CHARINDEX(' ',EmployeeName),LEN (SUBSTRING( EmployeeName,CHARINDEX(',',EmployeeName),LEN(EmployeeName)))) as[Middle name ]
FROM test$`
Here's a perfect reason why you should normalize your data.
declare #table table(thename varchar(500))
insert into #table
values
('Andrade, Maria Sandra'),
('Andrade, Maria'),
('Andrade, Maria Sandra OhSnap')
select
left(thename,CHARINDEX(',',thename) - 1) as LastName
,substring(thename,charindex(' ',thename),case when charindex(' ',thename) + charindex(' ',reverse(thename)) > len(thename) then charindex(' ',reverse(thename)) else len(thename) - (charindex(' ',thename) + charindex(' ',reverse(thename))) + 1 end) as FirstName
,case when charindex(' ',thename) + charindex(' ',reverse(thename)) - 1 = len(thename) then null else right(thename,charindex(' ',reverse(thename))) end as MiddleName
from #table

How to split the string in one column into two columns

I have a table like this
id value
------- ---------------
1 ind.kolkatta
2 ind.pune
3 ind.mumbai
4 pak.lahore
5 pak.karachi
6 uae.sharjah
I want to return the following table:
id contry place
------- --------- ----------
1 ind kolkatta
2 ind pune
3 ind mumbai
4 pak lahore
5 pak karachi
6 uae sharjah
how can i do that using MSSQL.? I have already done in MYSQL using SUBSTRING_INDEX function
My MySql query
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(`value`, '.', 1), '.', -1) as contry,
SUBSTRING_INDEX(SUBSTRING_INDEX(`value`, '.', 2), '.', -1) as place
FROM `table`
Try following query:-
SELECT ID, SUBSTRING(value, 1, CHARINDEX('.', value)-1) AS contry,
SUBSTRING(value, CHARINDEX(',', value)+1, LEN(value)) AS place
FROM YOUR_TABLE;
This might be helpful to you.
Hope the Below Query helps you.
SELECT id, SUBSTRING(value,1,3) as Country,SUBSTRING(value,4,LEN(value))AS Place FROM TableName
Try this:
SELECT Id,
LEFT(Value, CHARINDEX('.', Value)-1) AS Country,
STUFF(Value, 1, CHARINDEX('.', Value), '') AS Place
FROM Table
As per King King comment I checked the following
SELECT Id,
PARSENAME(value, 2) AS Country,
PARSENAME(Value, 1) AS Place
FROM Table
The above one worked, but I not sure about the version supported (I am using SSMS 2012).
Or just loop and it will parse out how ever many periods you have in your name.
DECLARE #FILE VARCHAR(55) = 'ind.kol.katta.test1.test2.test3.test4'
DECLARE #FILEFUN AS VARCHAR(55) = LEFT(#FILE,CHARINDEX('.',#FILE))
DECLARE #FILENAMEOUTPUT AS TABLE(Name Varchar(55))
WHILE LEN(#FILE) > 0
BEGIN
INSERT INTO #FILENAMEOUTPUT
SELECT REPLACE(#FILEFUN,'.','')
SET #FILE = REPLACE(#FILE,#FILEFUN,'')
SET #FILEFUN = iif(CHARINDEX('.',#FILE)=0,#FILE,LEFT(#FILE,CHARINDEX('.',#FILE)))
END
SELECT * FROM #FILENAMEOUTPUT

Splitting a single column (name) into two (forename, surname) in SQL

Currently I'm working on a database redesign project. A large bulk of this project is pulling data from the old database and importing it into the new one.
One of the columns in a table from the old database is called 'name'. It contains a forename and a surname all in one field (ugh). The new table has two columns; forenames and surname. I need to come up with a clean, efficient way to split this single column into two.
For now I'd like to do everything in the same table and then I can easily transfer it across.
3 columns:
Name (the forename and surname)
Forename (currently empty, first half of name should go here)
Surname (currently empty, second half of name should go here)
What I need to do: Split name in half and place into forename and surname
If anyone could shed some light on how to do this kind of thing I would really appreciate it as I haven't done anything like this in SQL before.
Database engine: MySQL
Storage engine: InnoDB
A quick solution is to use SUBSTRING_INDEX to get everything at the left of the first space, and everything past the first space:
UPDATE tablename
SET
Forename = SUBSTRING_INDEX(Name, ' ', 1),
Surname = SUBSTRING_INDEX(Name, ' ', -1)
Please see fiddle here. It is not perfect, as a name could have multiple spaces, but it can be a good query to start with and it works for most names.
Try this:
insert into new_table (forename, lastName, ...)
select
substring_index(name, ' ', 1),
substring(name from instr(name, ' ') + 1),
...
from old_table
This assumes the first word is the forename, and the rest the is lastname, which correctly handles multi-word last names like "John De Lacey"
For the people who wants to handle fullname: John -> firstname: John, lastname: null
SELECT
if( INSTR(`name`, ' ')=0,
TRIM(SUBSTRING(`name`, INSTR(`name`, ' ')+1)),
TRIM(SUBSTRING(`name`, 1, INSTR(`name`, ' ')-1)) ) first_name,
if( INSTR(`name`, ' ')=0,
null,
TRIM(SUBSTRING(`name`, INSTR(`name`, ' ')+1)) ) last_name
It works fine with John Doe. However if user just fill in John with no last name, SUBSTRING(name, INSTR(name, ' ')+1)) as lastname will return John instead of null and firstname will be null with SUBSTRING(name, 1, INSTR(name, ' ')-1).
In my case I added if condition check to correctly determine lastname and trim to prevent multiple spaces between them.
This improves upon the answer given, consider entry like this "Jack Smith Smithson", if you need just first and last name, and you want first name to be "Jack Smith" and last name "Smithson", then you need query like this:
-- MySQL
SELECT
SUBSTR(full_name, 1, length(full_name) - length(SUBSTRING_INDEX(full_name, ' ', -1)) - 1) as first_name,
SUBSTRING_INDEX(full_name, ' ', -1) as last_name
FROM yourtable
Just wanted to share my solution. It also works with middle names. The middle name will be added to the first name.
SELECT
TRIM(SUBSTRING(name,1, LENGTH(name)- LENGTH(SUBSTRING_INDEX(name, ' ', -1)))) AS firstname,
SUBSTRING_INDEX(name, ' ', -1) AS lastname
I had a similar problem but with Names containing multiple names, eg. "FirstName MiddleNames LastName" and it should be "MiddleNames" and not "MiddleName".
So I used a combo of substring() and reverse() to solve my problem:
select
SystemUser.Email,
SystemUser.Name,
Substring(SystemUser.Name, 1, instr(SystemUser.Name, ' ')) as 'First Name',
reverse(Substring(reverse(SystemUser.Name), 1, instr(reverse(SystemUser.Name), ' '))) as 'Last Name',
I do not need the "MiddleNames" part and maybe this is not the most efficient way to solve it, but it works for me.
Got here from google, and came up with a slightly different solution that does handle names with more than two parts (up to 5 name parts, as would be created by space character). This sets the last_name column to everything to the right of the 'first name' (first space), it also sets full_name to the first name part. Perhaps backup your DB before running this :-) but here it is it worked for me:
UPDATE users SET
name_last =
CASE
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 1)) = LENGTH(full_name) THEN ''
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 2)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -1)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 3)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -2)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 4)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -3)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 5)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -4)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 6)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -5)
ELSE ''
END,
full_name = SUBSTRING_INDEX(full_name, ' ', 1)
WHERE LENGTH(name_last) = 0 or LENGTH(name_last) is null or name_last = ''
SUBSTRING_INDEX didn't work for me in SQL 2018, so I used this:
declare #fullName varchar(50) = 'First Last1 Last2'
declare #first varchar(50)
declare #last varchar(50)
select #last = right(#fullName, len(#fullName)-charindex(' ',#fullName, 1)), #first = left(#fullName, (charindex(' ', #fullName, 1))-1);
Yields #first = 'First', #last = 'Last1 Last2'

mysql insert concatenate a constant value

I want to insert a constant called TUC and concatenate it with the initials of FirstName and LastName id of table.
id - 1
fname - James
lname - Bond
id - 2
fname - Daniel
lname - Edgar
eg. TUCJB001, TUCDE002,....
something like this
update tab
SET newid=CONCAT('TUC', LEFT(fname, 1), LEFT(lname, 1), LPAD(id,03, '0'));
Demo
Note If you want 4 digit number you will need do changes as highlighted below.
update tab
SET newid=CONCAT('TUC', LEFT(fname, 1), LEFT(lname, 1), LPAD(id,digit_range, '0'));
^^^^^^^^^^^
You can use something like this to get the value:
select
concat('TUC', left(firstname, 1), left(lastname, 1), '00', cast(id as char)) newValue
from yourtable
Then to update:
update yourtable
set yourColumn = concat('TUC', left(firstname, 1), left(lastname, 1), '00', cast(id as char))
See SQL Fiddle with Demo
UPDATE [table] SET [columnname] = CONCAT( UPPER(LEFT(fname, 1)), UPPER(LEFT(lname, 1)), LPAD(CONVERT(id, VARCHAR), 3, '0') );