Extract forename if the character is more then 2 letter - sql

I have to get the forename from the c.forename if c.known_as column is null or blank.
This i achieved with case when statement using
CASE
WHEN IND.KNOWN_AS IS NULL OR ind.KNOWN_AS=''
THEN ind.FORENAMES
ELSE ind.KNOWN_AS
END AS 'Known As'
My issue is in the forename column i have name like Jhon Smith where i would like to extract only John, below is an example what i want to achieve
Desire output c.forename
John Mr John
Jhon Jhon Smith
blank Jo
blank J
So , basically it will only take forname skipping 'Mr', 2nd it should take only forename which has more than 2 character.
My current query is:
Select ind.FORENAMES,
ind.KNOWN_AS,
case when (known_as is null or known_as = '' ) and charindex(' ', forenames) > 2
then substring(forenames, 1, charindex(' ', forenames) - 1) end as FORENAMES2,
output
from individual ind
join member m on m.individual_ref=ind.individual_ref
and m.MEMBERSHIP_NO in ('001','002','003','004','005','006','007')
where m.member_status=33

You could use following case when statement to verify your conditions:
For SQL Server:
case when (c.known_as is null or c.known_as = '' )
and charindex(' ', c.forename) > 3 then substring(c.forename, 1, charindex(' ', c.forename) - 1) end
For MySQL:
case when (c.known_as is null or c.known_as = '' )
and locate(' ', c.forename) > 3 then substring(c.forename, 1, locate(' ', c.forename) - 1) end
Little explanation: if the first name must be longer than 2 characters, that means that first space must occur at least at index 4. And that what the condition is about: locate(' ', c.forename) > 3 or substring(' ', c.forename) > 3
NOTE
You have to first strip down all occurences of Mr, Mrs, Ms in c.forename column, like this (syntax for MySQL and SQL Server):
replace(replace(replace(c.forename, 'Mrs ', ''), 'Mr ', ''), 'Ms ', '')
You have to include it in your query lke this:
Select FORENAMES,
KNOWN_AS,
case when (known_as is null or known_as = '' ) and charindex(' ', FORENAMES2) > 2
then substring(FORENAMES2, 1, charindex(' ', FORENAMES2) - 1) end as FORENAMES2,
output
from (
Select ind.FORENAMES,
ind.KNOWN_AS,
replace(replace(replace(ind.FORENAMES, 'Mrs ', ''), 'Mr ', ''), 'Ms ', '') FORENAMES2,
output
from individual ind
join member m on m.individual_ref = ind.individual_ref
where m.member_status=33
and m.MEMBERSHIP_NO in ('001','002','003','004','005','006','007')
)

Try this:
DECLARE #DataSource TABLE
(
[name] VARCHAR(32)
);
INSERT INTO #DataSource ([name])
VALUES (' Mr John ')
,('Jhon Smith')
,(' Jo ')
,(' J ');
WITH SanitizeDataSoruce ([name], [name_reversed]) AS
(
SELECT LTRIM(RTRIM([name]))
,REVERSE(LTRIM(RTRIM([name])))
FROM #DataSource
)
SELECT [name]
,CASE
WHEN CHARINDEX(' ', [name]) > 1 THEN REVERSE(SUBSTRING([name_reversed], 0, CHARINDEX(' ', [name_reversed])))
ELSE ''
END
FROM SanitizeDataSoruce;

Related

How to get the first letter of each word in SQL

I tried to run this query to get the initial letter of each word, and it worked for strings of 4 words, yet if the string has only two words, it duplicates the second word's initial.
select
substring(column_name, 1, 1) +
case
when 0 <> charindex(' ', column_name) + 1
then substring(column_name, charindex(' ',column_name) + 1, 1)
else ''
end +
case
when 0 <> charindex(' ', column_name, charindex(' ', column_name) + 1)
then substring(column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1, 1)
else ''
end +
case
when 0 <> charindex(' ', column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1)
then substring(column_name, charindex(' ', column_name, charindex(' ', column_name, charindex(' ', column_name) + 1) + 1) + 1, 1)
else ''
end
from table_name
You didn't specify which RDBMS you are using. This should work in SQL Server:
drop table if exists table_name
create table table_name (
column_name varchar(255)
)
insert table_name
values ('See Jane')
, ('See Jane run')
, ('See Jane run and jump over the lazy dog.')
select stuff((SELECT '' + t2.fc
from (
select left(str.value, 1) fc
, charindex(' ' + str.value + ' ', ' ' + t.column_name + ' ') idx
from string_split(t.column_name, ' ') str
) t2
order by t2.idx
FOR XML PATH('')
), 1, 0, '') as FirstChars
from table_name t
The idx column is used to order the ouptut because string_split does not promise to return the results in any particular order. Thanks to Aaron Bertrand - https://dba.stackexchange.com/questions/207274/string-split-and-ordered-results
Given the use of charindex in your question, I'm assuming you are using SQL Server. The CTE generates a tall view of your data using string_split function, with each letter on it's own row. We then select from it and group by id, and apply the string_agg function to place back into a single row.
Password guessing?
create table my_data (
id integer,
comments varchar(50)
);
insert into my_data (id, comments) values
(1, 'Thank goodness its friday'),
(2, 'I want 2 scoops of ice cream');
select * from my_data;
id
comments
1
Thank goodness its friday
2
I want 2 scoops of ice cream
with cte (id, first_char) as (
select id, substring(ss.value, 1, 1) as first_char
from my_data
cross apply string_split(comments, ' ')ss
)
select t.id,
string_agg(t.first_char, ',') as letters_delimited,
string_agg(t.first_char, '') as letters_not_delimited
from cte t
group by t.id
id
letters_delimited
letters_not_delimited
1
T,g,i,f
Tgif
2
I,w,2,s,o,i,c
Iw2soic
fiddle here
You can extend your approach with recursion
WITH cte_name AS (
select CONVERT(nvarchar(max), substring(column_name, 1, 1)) conc,
column_name n,
charindex(' ', column_name, 0) pos
from table_name
UNION ALL
select conc + substring(n, pos + 1, 1) as conc,
n,
charindex(' ', n, pos + 1) pos
from cte_name where pos > 0
)
SELECT *
FROM cte_name
where pos = 0;

I'm having trouble separating the first name from the middle name column in SQL Server 2017

I created this syntax to separate first name, middle name and last name from a column called invertornames. Just to note that the investor names are in arabic and their middle names are more than 3 words. It worked fine but the first name is also being included in the middle name as you can see below in the image
This is the query I wrote:
SELECT
SUBSTRING(investor_name, CHARINDEX(', ', investor_name) + 2, CASE WHEN CHARINDEX(' ', investor_name, CHARINDEX(', ', investor_name) + 2) = 0 THEN LEN(investor_name) + 1 ELSE CHARINDEX(' ', investor_name, CHARINDEX(', ', investor_name) + 2) END - CHARINDEX(', ', investor_name) - 2)AS FirstName,
RTRIM(LTRIM(REPLACE(REPLACE(investor_name,SUBSTRING(investor_name , 1, CHARINDEX(' ', investor_name) -1),''),REVERSE( LEFT( REVERSE(investor_name), CHARINDEX(' ', REVERSE(investor_name))-1 ) ),''))) AS MiddleName,
RIGHT(investor_name, CHARINDEX(' ', REVERSE(investor_name))) AS LastName
FROM
investornames
If you need any data to try it please let me know.
You may try this. I consider that First word is considered as Firstname, second word is considered as MiddleName and remaining word will considered as LastName.
For the case of arabic names. Software will not automatically detect that for which name calculation start from the front and for which it is taken in reverse. So I guess you need to maintain a flag for same.
In case of arabic name in the portion of cte use reverse to arrange them in left to right order instead of right to left order. And at the end use reverse function again to convert them into their original state.
Hope I am clear about what I am explaining. Sample code is following :-
; with cte as (
select 'Deepak kumar singh' as names
union
select 'Deep'
union
select 'deep kumar'
union
select 'Deepak kumar singh chandel')
SELECT
Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 1)) As [FirstName]
, Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) As [MiddleName]
, case when len( Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 3)))>0 then substring ( names ,
charindex ( Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ', names) + len(Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ') + 1
, len(names) - charindex ( Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ', names) + len(Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ')) else null end
As [LastName]
FROM (Select names from cte ) As [x]
Result of above query is:
FirstName MiddleName LastName
Deep NULL NULL
deep kumar NULL
Deepak kumar singh
deepak kumar singh chandel
Edit
Updated this ans check this
; with cte as (
select ' شركة عبدالمحسن عبدالعزيزالبابطين ' as names
union
select 'شركة'
union
select 'عبدالمحسن عبدالعزيز'
union
select 'البابطين')
, ct as (
select RTRIM(LTRIM(names)) as Names from cte )
SELECT
Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 1)) As [FirstName]
, Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) As [MiddleName]
, case when len( Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 3)))>0 then substring ( names ,
charindex ( Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ', names) + len(Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ') + 1
, len(names) - charindex ( Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ', names) + len(Reverse(ParseName(Replace(Reverse(names), ' ', '.'), 2)) + ' ')) else null end
As [LastName]
FROM (Select names from ct ) As [x]
Result
FirstName MiddleName LastName
???? ????????? ?????????????????
???? NULL NULL
???????? NULL NULL
????????? ????????? NULL
Here I am expecting on place of ? you'll get your result. BTW I've updated my query, have you tried this one. Just give one more try.

How to remove second occuring space in handphone number using sql server query

For example my handphone number is 123 456 789 i need output as 123 456789.
How to achieve this?
The logical approach here is to split the string into two sections using CHARINDEX and SUBSTRING, up to the first space, and after the first space, then REPLACE the string after the first space, then use CONCAT to put the string back together. e.g.
DECLARE #s VARCHAR(15) = '123 456 789';
SELECT BeforeSpace = SUBSTRING(#s, 1, CHARINDEX(' ', #s)),
AfterSpace = SUBSTRING(#s, CHARINDEX(' ', #s), LEN(#s)),
ReplaceAfterSpace = REPLACE(SUBSTRING(#s, CHARINDEX(' ', #s), LEN(#s)), ' ', ''),
Result = CONCAT(SUBSTRING(#s, 1, CHARINDEX(' ', #s)),
REPLACE(SUBSTRING(#s, CHARINDEX(' ', #s), LEN(#s)), ' ', ''));
However, it is actually simpler, to remove all spaces using REPLACE and re-insert a space where the first one was originally using STUFF:
DECLARE #s VARCHAR(15) = '123 456 789';
SELECT STUFF(REPLACE(#s, ' ', ''), CHARINDEX(' ', #s), 0, ' ');
All that is left to do then is check for cases where there is no space. Full example:
DECLARE #T TABLE (s VARCHAR(15));
INSERT #T VALUES ('123 456 789'), ('123456789'), ('123456 789'), ('123 4 5 6 789');
SELECT Original = s,
Method1 = CASE WHEN CHARINDEX(' ', s) = 0 THEN s
ELSE CONCAT(SUBSTRING(s, 1, CHARINDEX(' ', s)),
REPLACE(SUBSTRING(s, CHARINDEX(' ', s), LEN(s)), ' ', ''))
END,
Method2 = CASE WHEN CHARINDEX(' ', s) = 0 THEN s
ELSE STUFF(REPLACE(s, ' ', ''), CHARINDEX(' ', S), 0, ' ')
END
FROM #T;
Output
Original Method1 Method2
-------------------------------------------
123 456 789 123 456789 123 456789
123456789 123456789 123456789
123456 789 123456 789 123456 789
123 4 5 6 789 123 456789 123 456789
N.B I have made an assumption that when you say you want to replace the 2nd space, that you want to replace all spaces apart from the first. If my assumption is wrong, and it is only the 2nd space you want to replace then this won't work.
This should do it:
DECLARE #number AS NVARCHAR(12);
SELECT #number = '123 456 789';
SELECT STUFF(#number, CHARINDEX(' ', #number, CHARINDEX(' ', #number) + 1), 1, '') AS REMOVED_SECOND_SPACE;
DECLARE #s VARCHAR(12) = '111 222 333'
SELECT SUBSTRING(#s, 0, LEN(#s) - CHARINDEX(' ', REVERSE(#s)) + 1)
+ SUBSTRING(#s, LEN(#s) - CHARINDEX(' ', REVERSE(#s)) + 2, CHARINDEX(' ', REVERSE(#s)));
Well, in addition to other answers, I'll post the simpliest, based on assumption, that you want to have three digits followed by space, then the rest:
declare #x1 varchar(15), #x2 varchar(15), #x3 varchar(15), #x4 varchar(15), #x5 varchar(15)
set #x1 = '123456789'
set #x2 = '123 456789'
set #x3 = '123 456 789'
set #x4 = '123456 789'
set #x5 = '1 2 3 4 5 6 7 8 9'
select stuff(replace(#x1, ' ', ''), 4, 0, ' ')
select stuff(replace(#x2, ' ', ''), 4, 0, ' ')
select stuff(replace(#x3, ' ', ''), 4, 0, ' ')
select stuff(replace(#x4, ' ', ''), 4, 0, ' ')
select stuff(replace(#x5, ' ', ''), 4, 0, ' ')
All outputs will be the same: 123 456789.

Error: invalid length parameter passed to the right function in name parsing script

I gotta problem. When I run the below code I get an error saying:
invalid length parameter passed to the right function. What does that mean and how can it go away? Its to parse a name like smith, steve s to steve r smith in columns firstname, middlename and lastname
UPDATE table5
SET lastName = LEFT(Name, CHARINDEX(', ', Name) - 1),
firstname = SUBSTRING(Name,
CHARINDEX(', ', Name) + 2,
CASE
WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) + 1
ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2)
END - CHARINDEX(', ', Name) - 2
),
middlename= RIGHT(Name,
LEN(Name) - CASE
WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name)
ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2)
END
)
the "name" column is varchar (50) and firstname, middlename and lastname columns are also set to varchar (50) . I'm kinda stumped.. thanks in advance
The error is because CHARINDEX() is returning 0 and SUBSTRING() require at number bigger than 0. Your assumption is correct string without middle name will give you error.
Can you check this fiddle and let me know if that is the format you are using for name. Because the Gordon Linoff query seem to be working for select
SQL FIDDLE
NOTE:
I update the SqlFiddle with
WHERE CHARINDEX(', ', Name) > 0
My guess is some of your name doesnt have ,
You can validate doing
SELECT Name
FROM test
WHERE CHARINDEX(', ', Name) = 0
You can also check your other CHARINDEX condition with your data to see which one RETURN 0
I would prefer to write a function, Here is the code.
IF object_id(N'udf_NameSplitter', N'FN') IS NOT NULL
DROP FUNCTION udf_NameSplitter
GO
CREATE FUNCTION udf_NameSplitter
(
#FullName VARCHAR(50),
#NameSplitCharacter CHAR(1),
#NamePart CHAR(50) /*FN-firstname,MN-middlName,LN-lastName*/
)
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT, #NameTblString VARCHAR(50)
DECLARE #NameTbl TABLE (ID INT Identity(1,1),Item NVARCHAR(1000))
SET #StartIndex = 1
IF SUBSTRING(#FullName, LEN(#FullName) - 1, LEN(#FullName)) <> #NameSplitCharacter
BEGIN
SET #FullName = #FullName + #NameSplitCharacter
END
WHILE CHARINDEX(#NameSplitCharacter, #FullName) > 0
BEGIN
SET #EndIndex = CHARINDEX(#NameSplitCharacter, #FullName)
INSERT INTO #NameTbl(Item)
SELECT SUBSTRING(#FullName, #StartIndex, #EndIndex - 1)
SET #FullName = SUBSTRING(#FullName, #EndIndex + 1, LEN(#FullName))
END
SELECT #NameTblString = LTRIM(RTRIM(Item))
FROM #NameTbl
WHERE ID = CASE WHEN #NamePart = 'LN' THEN 1 WHEN #NamePart = 'FN' THEN 2 ELSE 3 END
RETURN (#NameTblString)
END
GO
Test the function with a few scenarios. I think I covered most but its worth having a second look. I would highly recommend doing a select before an update and see if the data is accurate or as expected.
DECLARE #Name VARCHAR(50) = 'lastName , firstname ,middleName '
SELECT
lastName=dbo.udf_NameSplitter(#Name,',','LN'),
firstname=dbo.udf_NameSplitter(#Name,',','FN'),
middleName=dbo.udf_NameSplitter(#Name,',','MN')
Usage with your table
UPDATE table5
SET lastName=LEFT(Name, CHARINDEX(', ', Name) - 1),
firstname=SUBSTRING(Name, CHARINDEX(', ', Name) + 2, CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) + 1 ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END - CHARINDEX(', ', Name) - 2),
middlename=RIGHT(Name, LEN(Name) - CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END)
It means that charindex() is returning 0, which you are passing to another function. One way to fix this is:
UPDATE table5
SET lastName=LEFT(Name, CHARINDEX(', ', Name) - 1),
firstname=SUBSTRING(Name, CHARINDEX(', ', Name) + 2, CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) + 1 ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END - CHARINDEX(', ', Name) - 2),
middlename=RIGHT(Name, LEN(Name) - CASE WHEN CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) = 0 THEN LEN(Name) ELSE CHARINDEX(' ', Name, CHARINDEX(', ', Name) + 2) END)
WHERE Name LIKE '% % %';
This ensures that Name has two spaces, which your logic is assuming.
select left(RTRIM(ltrim(C_Subarea_Code)),2) +
right(RTRIM(ltrim(C_Subarea_Code)),len(RTRIM(ltrim(C_Subarea_Code)))-3)
from Tbl_Doc_Stock_Chem_Add_Mst
in sql

How do I split and comma-delimit names?

I have this column
NAME
John Stephenson
James Martin
Anna Corelia
How I can select this column to this?
NAME
Stephenson, John
Martin, James
Corelia, Anna
One way
;with test(name) as (
select 'John Stephenson' union all
select 'James Martin' union all
select 'Anna J. Corelia' union all
select 'BOBBYTABLES'
)
select
case when charindex(' ', name) = 0 then name
else right(name, charindex(' ', reverse(name)) - 1) + ', ' + substring(name, 1, len(name) - charindex(' ', reverse(name))) end
from test
(No column name)
Stephenson, John
Martin, James
Corelia, Anna J.
BOBBYTABLES
Your question has nothing to do with TRIM() function. Probably you are trying to get something like below using LEFT() and RIGHT() function of SQL Server and concatanating them with ,
select right('John Stephenson',(len('John Stephenson')-charindex(' ','John Stephenson')))
+ ', ' + left('John Stephenson',(charindex(' ','John Stephenson') - 1))
which will result in
Stephenson, John
Here is a solution including how I got the final output column.
This will handle three part names, like "Rip Van Winkle", also names with no white space and will strip (trim) any leading/trailing white space from the names.
DECLARE #NAMES TABLE (NAME NVARCHAR(MAX))
INSERT INTO #NAMES (NAME) VALUES ('John Stephenson'),('James Martin'),('Anna Corelia'),('Rip Van Winkle'),('Sally')
SELECT *,
CHARINDEX(' ',LTRIM(RTRIM(NAME))) [SpaceLocation],
CASE WHEN CHARINDEX(' ',LTRIM(RTRIM(NAME)))>0 THEN RIGHT(LTRIM(RTRIM(NAME)), LEN(LTRIM(RTRIM(NAME)))-CHARINDEX(' ',LTRIM(RTRIM(NAME)))) END [LastName],
CASE WHEN CHARINDEX(' ',LTRIM(RTRIM(NAME)))>0 THEN LEFT(LTRIM(RTRIM(NAME)),CHARINDEX(' ',LTRIM(RTRIM(LTRIM(RTRIM(NAME)))))-1) END [FirstName],
CASE WHEN CHARINDEX(' ',LTRIM(RTRIM(NAME)))>0 THEN RIGHT(LTRIM(RTRIM(NAME)), LEN(LTRIM(RTRIM(NAME)))-CHARINDEX(' ',LTRIM(RTRIM(NAME)))) + ', ' +LEFT(LTRIM(RTRIM(NAME)),CHARINDEX(' ',LTRIM(RTRIM(NAME)))-1) ELSE LTRIM(RTRIM(NAME)) END [FinalOutput]
FROM #NAMES
SELECT substring(NAME+', '+NAME,charindex(' ',NAME)+1,len(NAME)+1) FROM MyTable
This also turns "Rip Van Winkle" into "Van Winkle, Rip"
SQL Fiddle Demo
There is no a single trim function but you can
select ltrim(rtrim(colname)) from tablename
which will TRIM both sides.
but what you need is:
declare #name varchar(300) ='Stephenson John';
Select
Substring(#name, 1,Charindex(' ', #name)-1) +
', ' +
Substring(#name, Charindex(' ', #name)+1, LEN(#name))
as name
Sorry I miss post