Detect double value in MySQL - mysql

I have an InnoDB table with fields
firstname, lastname
While displaying names, usually only firstname is enough. Sometimes users have the same first name; so I have to get firstname and first letter of lastname:
CONCAT(firstname, ' ', SUBSTRING(lastname, 1, 1), '.')
Is there a (performant) way to only display the first letter of the last name in case of a double first name? Something like
WHEN isDouble(Firstname) THEN
CONCAT(firstname, ' ', SUBSTRING(lastname, 1, 1), '.')
ELSE firstname
/* edit */
Forgot to mention the solution I was thinking of:
Creating a column 'double_firstname', with value 1 or 0, and use a CASE statement to select. Then update the double_firstname column on user create and delete.

You can of course ask mysql if the number of entries for that firstname is bigger than one, so:
select IF( (select count(*) as cnt from person where firstname = p.firstname) > 1
, concat(firstname, " ", substring(lastname, 1))
, firstname)
from person
where id = 4711
;
But that is not very quick.
Better for a higher number of persons is a stable mark on person how to "call" her. That could be "firstname lastname" initially and then get more personally with reducing to firstname by a cronjob. It also could mean to call "John Doe" just John, because he entered early, and "John DaSecond" call "John D.", and "JohnDaThird" call "John DaT.".
JohnD is not unique in that scenario.
Is John Doe informed about being renamed to "John D." in your Scenario?

You asked for good performance as well as the ability to do it. If you have an index on names(firstname, lastname) the following should perform well:
select (case when exists (select 1
from names n2
where n2.firstname = n.firstname and n2.lastname <> n.lastname
)
then concat(firstname, ' ', left(lastname, 1))
else firstname
end)
from names n

Related

Issue with MySQL Concat and like command

I want to validate the data in MYSQL table. Table has 4 fields :
Firstname
Middlename
Lastname
Fullname
I want to compare if CONCAT(firstname, ' ', LASTNAME), matches Fullname
Here is the command I am using :
select * from user_info where CONCAT(firstname, ' ', lastname)
like CONCAT('%', fullname, '%')
However, this is not working. But the following command works :
select * from user_info where CONCAT(firstname, ' ', lastname)
like '%JOHN DOE%'
What could be the issue with the MySQL command ?
Your newly attached data confirms what I suspected, namely that the full name is not necessarily composes simply of the first and last name, but include the middle name, or might even be missing any of the three components. One option here would be to assert that each component present does appear somewhere inside the full name, in the correct order, e.g.
SELECT *
FROM yourTable
WHERE
fullname REGEXP
CONCAT(
CASE WHEN firstname IS NOT NULL
THEN CONCAT('[[:<:]]', COALESCE(firstname, ''), '[[:>:]]')
ELSE '' END,
'.*',
CASE WHEN middlename IS NOT NULL
THEN CONCAT('[[:<:]]', COALESCE(middlename, ''), '[[:>:]]')
ELSE '' END,
'.*',
CASE WHEN lastname IS NOT NULL
THEN CONCAT('[[:<:]]', COALESCE(lastname, ''), '[[:>:]]')
ELSE '' END);
Demo
You need to change order of condition in your code :-
select * from table1 where fullname
like CONCAT('%', trim(CONCAT(firstname,' ',middlename,' ',lastname)) , '%')
SQL Fiddle

How can I extract a last name from full name in mysql?

I have a table with fullname column. I want to make a query for finding a person via his last name but his last name is in the full name column.
Would it matter if it accidentally returned someone whose first name matched your query?
A simple query would be:
SELECT *
FROM TABLE
WHERE fullname LIKE '%insertlastname%'
If you want to define the last name as the name after the last space:
SELECT substring_index(fullname, ' ', -1) as lastname
FROM TABLE
WHERE lastname='insertlastname'
Two suboptimal answers, but some answers at least.
enter code here You can use this if you want to fetch by query:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( `fullname` , ' ', 2 ),' ',1) AS b,
SUBSTRING_INDEX(SUBSTRING_INDEX( `fullname` , ' ', -1 ),' ',2) AS c FROM `users` WHERE `userid`='1'
But you can also try by PHP to fetch last name. You just use explode function to fetch last name.
Exm:
$full_name = "row moin";
$pieces = explode(" ", $fullname);
echo $first_name = $pieces[0]; // row
echo $last_name = $pieces[1]; // moin
A simple answer for this is like this suppose we have a name
Charles Dickens
:
SELECT * FROM TABLE_NAME WHERE SUBSTRING_INDEX(FULLNAME,' ',-1) like '%Dickens';

Change position of last name and rest of name in MySQL query

My 'name' column has names stored like this
Lastname Firstname Middlename
I want to display it like this in my query:
Firstname Middlename Lastname
Not all records have a middle name, so they may be 1 or 2 spaces in the column
I have tried this :
SELECT CONCAT ( SUBSTRING_INDEX(`name`, ' ', 1) , ' ' , SUBSTRING_INDEX(`name`, ' ', -1) ) AS nicename`
But this only gives the last name. The "-1" part is not working...
Thanks for all help.
To start with, that's a bad design, Now, since your middlename part may be empty, you may bear with it and just select the name saying select name from tbl1.
Else, consider re-designing your table to have separate columns for Lastname, Firstname and Middlename and then You don't need all of this. You can just get data from all 3 columns saying
select concat(Firstname, Middlename, Lastname ) as nicename
from tbl1;
Found a solution :
SELECT concat ( TRIM( SUBSTR(`name`, LOCATE(' ', `name`)) ), ' ', SUBSTRING_INDEX(SUBSTRING_INDEX(`name`, ' ', 1), ' ', -1) ) as nicename
Source: How to split the name string in mysql?

MySQL Replace String "John Doe" with "John D"

Have a large name table all as string "Name Surname"
Need to update the entire table, setting the string to be "Name FirstLetterOfSurname" ie. "John Citizen" becomes "John C".
Seems easier to do via PHP eg.
$name = "John Doe";
$expl = explode(' ', $name);
echo $expl [0].' '.$expl[1][0];
John D
wondering about a query to just update the database.
Help Appreciated?
I'd find the location of the space, and take a substring of one character more than that:
SELECT SUBSTR(name, 1, LOCATE(' ', name) + 1)
FROM mytable
Of course, this can also be done as an update instead of just querying the string in the right format:
UPDATE mytable
SET name = SUBSTR(name, 1, LOCATE(' ', name) + 1)
If you want to update the database, please use the following query:
UPDATE TestTable
SET FirstName = CONCAT(LEFT(FirstName, INSTR(FirstName, ' ')) , LEFT(SUBSTRING(FirstName, INSTR(FirstName, ' ') + 1), 1)) ;
Please find the Working Demo with sample data.

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'