I have the following syntax on my SELECT Statement:
CONCAT(first_name, " ", COALESCE(middle_initial), " ", last_name) AS full_name
Obviously, what I get is the following:
For first_name='John' and middle_initial='A.' and last_name='Smith'
I get 'John A. Smith'
That is fine and is the desired result.
But I get an extra space for the following data (which I clearly understand why):
For first_name='John' and middle_initial='' and last_name='Smith'
I get 'John Smith'
Is there a way with COALESCE() to append " " if the condition returns a non-null value?
Thank you.
When middle_initial has '', you would want to:
SELECT CONCAT(first_name, ' ',
CASE
WHEN middle_initial is null OR middle_initial = '' then ''
ELSE CONCAT(middle_initial, ' ')
END
, last_name) AS full_name
SQLFiddle Example
COALESCE is used for checking NULL values, not handling empty strings, ''
select concat(first_name , ' ' ,
case when middle_initial is null then ''
when middle_initial = '' then ''
else concat(middle_initial, ' ') end ,
last_name)
this query asumes that first_name and last_name are not null nor empty string, in that case you can apply same logic to that fields
Try this
SELECT rtrim(Coalesce(first_name + ' ','')
+ Coalesce(nullif(middle_name,'') + ' ', '')
+ Coalesce(nullif(last_name,'') + ' ', ''))
FROM #table
SELECT rtrim(Coalesce('John' + ' ','')
+ Coalesce(nullif('A.','') + ' ', '')
+ Coalesce(nullif('Smith','') + ' ', ''))
SELECT rtrim(Coalesce('John' + ' ','')
+ Coalesce(nullif('','') + ' ', '')
+ Coalesce(nullif('Smith','') + ' ', ''))
I think best way is to do it like this. You can use such a constraction for any number of fields, variables and so on. Also it will correctly show you John or John A.
declare #Temp_Table table (first_name nvarchar(128), middle_initial nvarchar(128), last_name nvarchar(128))
insert into #Temp_Table
select 'John', null, 'Smith' union all
select 'John', 'A.', 'Smith' union all
select 'John', 'A.', null union all
select 'John', null, null
select
*,
stuff
(
isnull(' ' + nullif(first_name, ''), '') +
isnull(' ' + nullif(middle_initial, ''), '') +
isnull(' ' + nullif(last_name, ''), ''),
1, 1, ''
)
from #Temp_Table
Related
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.
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;
I am trying to add a computed column to an SQL database. The Computed Column Specification looks like this
BusinessName + ' ' + Surname + ' ' + FirstName
which works fine.
Often the BusinessName is blank so I want to Trim it
Trim(BusinessName + ' ' + Surname + ' ' + FirstName)
But when I do I get an error
You can use below logic,
First option: check if value is null, replace it by empty string, you will have leading empty space if BusinessName is null
isnull(BusinessName, '') + ' ' + Surname + ' ' + FirstName
or
Second option: check if BusinessName is empty or null, do not take into account if so. You won't have leading empty space if BusinessName is null or empty
case when isnull(BusinessName, ' ') <> ' '
then BusinessName + ' ' + Surname + ' ' + FirstName
else Surname + ' ' + FirstName
end as FullName
I think it depends by column datatypes and constraints. A more general approach could be the following. Starting from this if as a rule SURNAME and NAME (for instance) are not NULLABLE and cannot be blank, you can omit some of the functions:
DECLARE #T AS TABLE (BUSIN_NAME VARCHAR(20), SURNAME VARCHAR(20), NAME VARCHAR(20))
INSERT INTO #T VALUES(NULL, NULL, NULL);
INSERT INTO #T VALUES(NULL, 'A', NULL);
INSERT INTO #T VALUES(NULL, 'B ', NULL);
INSERT INTO #T VALUES('', 'Karl ', ' Smith');
INSERT INTO #T VALUES('Dr.', 'Karl ', ' Smith');
INSERT INTO #T VALUES('Dr. ', 'Joe ', ' Martin ');
SELECT BUSIN_NAME, SURNAME, NAME
, LTRIM(RTRIM( LTRIM(RTRIM(ISNULL(BUSIN_NAME,'')))+ ' ' + LTRIM(RTRIM(ISNULL(SURNAME,'')))+' ' +LTRIM(RTRIM(ISNULL(NAME,''))))) DESCR
, DATALENGTH ( LTRIM(RTRIM( LTRIM(RTRIM(ISNULL(BUSIN_NAME,'')))+ ' ' + LTRIM(RTRIM(ISNULL(SURNAME,'')))+' ' +LTRIM(RTRIM(ISNULL(NAME,''))))) ) AS LENGTH
FROM #T
OUtput:
BUSIN_NAME SURNAME NAME DESCR LENGTH
NULL NULL NULL 0
NULL A NULL A 1
NULL B NULL B 1
Karl Smith Karl Smith 10
Dr. Karl Smith Dr. Karl Smith 14
Dr. Joe Martin Dr. Joe Martin 14
I would suggest doing the following:
select stuff( (coalesce(' ' + BusinessName, '') +
coalesce(' ' + Surname, '') +
coalesce(' ' + Firstname, '')
), 1, 1, '')
These easily generalizes to more fields. You can use ltrim() rather than stuff(), because you are using spaces as a separator. stuff() is more general, because it handles other separators (notably commas).
As a computed column:
alter table t add newcol as
(stuff( (coalesce(' ' + BusinessName, '') +
coalesce(' ' + Surname, '') +
coalesce(' ' + Firstname, '')
), 1, 1, ''
)
)
I posted a similar question a while back and now as I need to update this code, I am back to ask a follow-on question. Previous question is here:
Computed column based on nullable columns
My data (Address1, Address2, City, State, Zip, Country) may have incomplete information. I.e. I can't be guaranteed that anything other than State and Country columns will have data.
I would like to have a computed columns for FullAddress.
Previously, I used COALESCE, which worked great if all fields are filled in. Now, as the data requirements have been relaxed, this is no longer an option (because we end with repeated commas in the FullAddress). Here is what I have been using previously (note, I'm just working with SELECT statements here for ease of use - will convert into a computed columns "alter table add" statement once I have something that works for all cases):
SELECT (((((COALESCE([Address1],'')
+ COALESCE(', '+[Address2],''))
+ COALESCE(', '+[City],''))
+ COALESCE(', '+[State],''))
+ COALESCE(', '+[Zip],''))
+ COALESCE(', '+[Country],'')) AS FullAddress
FROM Locations
Now, I have put together an alternative using CASE, but it still doesn't work for the edge case where Address1 is NULL (the problem is that the FullAddress will have ', ' as the first two characters)
SELECT CASE WHEN [Address1] IS NOT NULL THEN [Address1] ELSE '' END
+ CASE WHEN [Address2] IS NOT NULL THEN ', ' + [Address2] ELSE '' END
+ CASE WHEN [City] IS NOT NULL THEN ', ' + [City] ELSE '' END
+ CASE WHEN [State] IS NOT NULL THEN ', ' + [State] ELSE '' END
+ CASE WHEN [Zip] IS NOT NULL THEN ', ' + [Zip] ELSE '' END
+ CASE WHEN [Country] IS NOT NULL THEN ', ' + [Country] ELSE '' END
AS [FullAddress]
FROM Locations
I'm a little stuck at this point. Any recommendations what to try next?
you can use this pattern:
SELECT
ISNULL(Address1 + ', ', '')
+ ISNULL(Address2 + ', ', '')
+ ISNULL(City + ', ', '')
-- ....
AS FullAddress
The result of concation NULL + ', ' is NULL => Address1 + ', ' will be NULL or valid address => ISNULL(Address1 + ', ', '') will be empty string or valid address.
SELECT STUFF(
COALESCE(', ' + Address1, '') + COALESCE(', ' + Address2, '') + ...
1,
2,
''
) AS FullAddress
FROM Locations
The concatenated string will either be empty or start with , (a comma and a space). STUFF() will remove the first two characters and return the rest of the string.
I'm trying not to reinvent the wheel here...I have these four fields:
[tbl_Contacts].[FirstName],
[tbl_Contacts].[MiddleInitial],
[tbl_Contacts].[LastName],
[tbl_Contacts].[Suffix]
And I want to create a FullName field in a view, but I can't have extra spaces if fields are blank...
So I can't do FirstName + ' ' + MiddleInitial + ' ' + LastName + ' ' + Suffix... Because if there is no middle initial or suffix I'd have 2 extra spaces in the field. I think I need a Case statement, but I thought someone would have a handy method for this...Also, the middleinitial and suffix may be null.
Assuming that all columns could be nullable, you can do something like:
RTrim(Coalesce(FirstName + ' ','')
+ Coalesce(MiddleInitial + ' ', '')
+ Coalesce(LastName + ' ', '')
+ Coalesce(Suffix, ''))
This relies on the fact that adding to a NULL value yields a NULL.
Whichever options you choose, here's something to think about: this will be a rather involved and thus time consuming option, especially if you have it in a view which gets evaluated each and every time for each and every row in question.
If you need this frequently, I would recommend you add this to your base table as a persisted, computed field - something like:
ALTER TABLE dbo.tbl_Contacts
ADD FullName AS (insert the statement of your choice here) PERSISTED
When it's persisted, it becomes part of the underlying table, and it's stored and kept up to date by SQL Server. When you query it, you get back the current value without incurring the cost of having to concatenate together the fields and determine which to use and which to ignore...
Just something to think about - something that too many DBA's and database devs tend to ignore and/or not know about....
You may want to pass the FirstName + ' ' + MiddleInitial + ' ' + LastName + ' ' + Suffix concatenation through the REPLACE() function in order to substitute duplicate spaces into a single space.
REPLACE(FirstName + ' ' + MiddleInitial + ' ' + LastName + ' ' + Suffix, ' ', ' ')
-- -- -
EDIT:
Just noticed that some of your fields may be NULL, and therefore the above would not work in that case, as the whole string would become NULL. In this case, you can use the COALESCE() method as suggested by Thomas, but still wrapped it in a REPLACE():
REPLACE(RTRIM(COALESCE(FirstName + ' ', '') +
COALESCE(MiddleInitial + ' ', '') +
COALESCE(LastName + ' ', '') +
COALESCE(Suffix, '')), ' ', ' ')
Test:
SELECT REPLACE(RTRIM(COALESCE('John' + ' ', '') +
COALESCE('' + ' ', '') +
COALESCE('Doe' + ' ', '') +
COALESCE(NULL, '')), ' ', ' ')
-- Returns: John Doe
I had to join Firstname, Middlename, and Lastname. my challenge was to handle NULL values, used following code.
RTRIM(LTRIM(RTRIM(isnull(#firstname,'') + ' ' + isnull(#middlename,'')) + ' ' + isnull(#lastname,'')))
Test different scenarios if you are interested :)
DECLARE #firstname VARCHAR(MAX)
DECLARE #middlename VARCHAR(MAX)
DECLARE #lastname VARCHAR(MAX)
set #firstname = 'FirstName'
set #middlename = NULL
set #lastname = 'LastName'
SELECT '|'+RTRIM(LTRIM(RTRIM(isnull(#firstname,'') + ' ' + isnull(#middlename,'')) + ' ' + isnull(#lastname,'')))+'|'
--
If you are using SQL Server 2012+ you could use CONCAT and +:
SELECT RTRIM(
CONCAT(FirstName + ' ', MiddleInitial + ' ', LastName + ' ', Suffix)
) AS [FullName]
FROM tbl_Contacts;
How it works:
If any part of full name is NULL then NULL + ' ' → NULL
CONCAT handles NULL
In case that after part of name there are only NULLs, TRIM last space.
LiveDemo
Here is a solution:
CREATE FUNCTION dbo.udf_IsNullOrEmpty
(
#vchCheckValue VARCHAR(MAX)
,#vchTrueValue VARCHAR(MAX)
,#vchFalseValue VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN CASE WHEN NULLIF(RTRIM(LTRIM(#vchCheckValue)),'') IS NULL THEN #vchTrueValue ELSE #vchFalseValue END
END
SELECT FirstName + ' ' +
dbo.udf_IsNullOrEmpty(MiddleInitial,'',MiddleInitial + ' ') +
LastName +
dbo.udf_IsNullOrEmpty(Suffix,'',' ' + Suffix)
FROM tbl_Contacts
select CONCAT(IFNULL(FirstName, ''),
'',
IFNULL(MiddleName, ''),
'',
IFNULL(LastName, '')) AS name
from table
Why not like this:
select concat(fName,' ',
case length(mName)
when 0 then ''
else concat(mName, ' ') end, lName) as fullName
My columns are not null, so this works for me.
create function getfname(#n varchar(30))
returns varchar(30)
as
begin
declare #s varchar(30)
set #s=LEFT(#n,charindex(' ',#n)-1)
return #s
end
create function getLname(#n varchar(30))
returns varchar(30)
as
begin
declare #s varchar(30)
set #s=substring(#n,charindex(' ',#n+1),Len(#n))
return #s
end
the query:
SELECT retire.employeehrmsid,
Isnull(retire.firstname, '') + ' '
+ Isnull(retire.middlename, '') + ' '
+ Isnull(retire.lastname, '') AS FullName,
retire.dojtoservice,
retire.designation,
emphistory.currentdoj,
emphistory.presentddo,
emphistory.office,
transfer.generatetid AS TransferID,
transfer.transferdate,
transfer.currentlocation,
transfer.newlocation,
transfer.datas AS Transfer_Doc,
release.generaterid AS ReleaseID,
release.releasedate,
release.datar AS Release_Doc,
employeeserviceupdate.dataeu AS Join_Doc
FROM retire
INNER JOIN emphistory
ON retire.id = emphistory.id
INNER JOIN employeeserviceupdate
ON retire.id = employeeserviceupdate.id
INNER JOIN transfer
ON retire.id = transfer.id
AND emphistory.ehrid = transfer.ehrid
INNER JOIN release
ON transfer.tid = release.tid