What's the shortest TSQL to concatenate a person's name which may contain nulls - sql

3 fields: FirstName, MiddleName, LastName
Any field can be null, but I don't want extra spaces. Format should be "First Middle Last", "First Last", "Last", etc.

LTRIM(RTRIM(
LTRIM(RTRIM(ISNULL(FirstName, ''))) + ' ' +
LTRIM(RTRIM(ISNULL(MiddleName, ''))) + ' ' +
LTRIM(ISNULL(LastName, ''))
))
NOTE: This won't leave trailing or leading spaces. That's why it's a little bit uglier than other solutions.

Assuming by "extra spaces", you mean extra spaces inserted during the concatenation (which is a reasonable assumption, I think. If you have extra spaces in your data, you should clean it up):
ISNULL(FirstName + ' ', '') + ISNULL(MiddleName + ' ', '') + ISNULL(LastName, '')
works, since you'll add a space to the name - which if it's NULL yields NULL - which yields empty string.
Edit: If you don't count the SET OPTION - which can be a connection or db option:
SET CONCAT_NULL_YIELDS_NULL OFF
LTRIM(FirstName + ' ' + NULLIF(MiddleName + ' ', ' ') + LastName)
is a tiny bit shorter, but a large bit uglier.
Edit2: Since you accepted the UDF answer - IMO, that's a bit of a cheat - here's some in the same vein:
SELECT a FROM b
b is a view. ;) Or. a stored proc,
EXEC c
But, since EXEC is optional:
c

use a UDF:
`Select udfConcatName(First, Middle, Last) from foo`
That way all your logic for concatenating names is in one place and once you've gotten it written it's short to call.

LTRIM(RTRIM(ISNULL(FirstName, '') + ' ' + LTRIM(ISNULL(MiddleName, '') + ' ' +
ISNULL(LastName, ''))))

Why not use a computed column on the table that performs the concat for you using your preferred syntax from the many posted here? Then you will just query the computed column - very elegant and if you persist the computed column then you may even get slight performance increase.
Example here

replace(ltrim(rtrim(isnull(FirstName, '') + ' ' + isnull(MiddleName, '') + ' ' + isnull(LastName, ''))), ' ', ' ')

'"' + ltrim(rtrim(isnull(FirstName,''))) + ' ' + ltrim(rtrim(isnull(MiddleName,''))) +
' ' + ltrim(rtrim(isnull(LastName,''))) + '","' + ltrim(rtrim(isnull(FirstName,''))) +
' ' + ltrim(rtrim(isnull(LastName,''))) + '","' + ltrim(rtrim(isnull(LastName,''))) +
'"'
ETC

DECLARE #first varchar(10) = 'First'
DECLARE #middle varchar(10) = ''
DECLARE #last varchar(10) = 'Last'
LTRIM(RTRIM(
#first
+ ISNULL(NULLIF(' '+LTRIM(RTRIM(#middle)),' '),'')
+ ISNULL(NULLIF(' '+LTRIM(RTRIM(#last)),' '),'')
))
WHY THIS WORKS
The fields are reduced to an empty string if NULL or whitespace by the LTRIM, RTRIM, and ISNULL functions.
LTRIM(RTRIM(ISNULL(#middle,''))) -- Result is a trimmed non-null string value.
That value is prefixed with a single space, then compared to a single space by the NULLIF function. If equal, a NULL results. If not equal, then the value is used.
NULLIF(' '+'',' ') -- this would return NULL
NULLIF(' '+'Smith',' ') -- this would return ' Smith'
Finally, ISNULL() is used to convert the NULL passed by NULLIF to an empty string.
ISNULL(NULL,'') -- this would return ''
ISNULL(' Smith','') -- this would return ' Smith'

LTrim(RTrim(Replace(IsNull(Firstname + ' ', '') +
isNull(MiddleName, '') +
IsNull(' ' + LastName, ''), ' ', ' ')))

Select firstname, middlename, lastname, ProvidedName =
RTrim(Coalesce(FirstName + ' ','')
+ Coalesce(MiddleName + ' ', '')
+ Coalesce(LastName + ' ', '')
+ COALESCE('' + ' ', '')
+ COALESCE(NULL, ''))
From names

Related

Eliminating a space in concatenated values when null

My SELECT statement reads something like this:
SELECT JKLL.LKJJ, LKJF.ASLKD, TRIM (ADDR.UNNBR) || ' ' || TRIM(ADDR.PREDIR) || ' ' ||, TRIM(ADDR.STREET)....
Where UNNBR is the address number and PREDIR is the predirection (NSEW).
When concatenating into the same column, if predir is null, I get two spaces between UNNBR and STREET, obviously.
Can I use a case statement to eliminate this space when PREDIR is null? If so, what would that syntax look like?
I sometimes do something like this for these situations:
(TSQL syntax)
SELECT
CASE WHEN ADDR.UNNBRIS IS NOT NULL THEN ADDR.UNNBR + ' ' ELSE '' END +
CASE WHEN ADDR.PREDIR IS NOT NULL THEN ADDR.PREDIR + ' ' ELSE '' END +
...
This way you only get the space if the field isn't null.
I would use ISNULL
SELECT JKLL.LKJJ, LKJF.ASLKD, TRIM(ADDR.UNNBR) + ISNULL(' ' + TRIM(ADDR.PREDIR),'') ...
A NULL value concatenated to anything yields a NULL. So something like this will work:
WITH ex as
(SELECT 'Pants' as item, null as other, 'George' as name)
SELECT COALESCE(item + ' ', '')
+ COALESCE(other + ' ', '')
+ COALESCE(name + ' ', '')
FROM ex

Concatenate and format text in SQL

I need to concatenate the City, State and Country columns into something like City, State, Country.
This is my code:
Select City + ', ' + State + ', ' + Country as outputText from Places
However, because City and State allow null (or empty) value, what happen is, (for example) if the City is null/empty, my output will look like , Iowa, USA; or say the State is empty, then the output will look like Seattle, , USA
Is there anyway I can format the output and remove "unnecessary" commas?
Edited: Because of the requirements, I should not use any other mean (such as PL/SQL, Store Procedure) etc., so it has to be plain SQL statement
select
isnull(City, '') +
case when isnull(City, '') != '' then ', ' else '' end +
isnull(State, '') +
case when isnull(State, '') != '' then ', ' else '' end +
isnull(Country, '') as outputText
from
Places
Since adding a string with null will result null so if they are null (not empty string) this will give you teh desired result
Select isnull(City + ', ','') + isnull(State + ', ' ,'') + isnull(Country,'') as outputText from Places
Use the COALESCE (Transact-SQL) function.
SELECT COALESCE(City + ', ', '') + COALESCE(State + ', ', '')...
In SQL Server 2012 you can use CONCAT function:
select concat(City,', ',State,', ',Country ) as outputText from Places
Not elegant by any means...
first changes city, state,country to null values if blank
then interprets that value for null and adds a space before a comma
then replaces any space comma space ( , ) with empty set.
Query:
SELECT replace(coalesce(Replace(City,'',Null),' ') + ', ' +
coalesce(Replace(State,'',Null), ' ' + ', ' +
coalesce(replace(Country,''Null),''), ' , ','') as outputText
FROM Places
Assumes no city state or country will contain space comma space.

SQL print a space between concat statements

Concatenating two columns together, Just want them to be displaying together in column with a space between the two numbers. It keeps adding the two numbers together. One is a bigint other is a smallint.Will be displayed in an SSRS report eventually but right now just using SQL to query the data
(NBR +''+ ACCT_NBR) as acct,
Though you didn't mention the database, try
MySQL
concat(NBR,' ',ACCT_NBR) as acct
SQL Server
CAST(NBR AS VARCHAR)+' '+CAST(ACCT_NBR AS VARCHAR) as acct
You don't mention what flavor of SQL you're using, but depending, you may need to convert the values to strings first. For SQLSever...
(Cast(NBR as varchar(20)) + ' ' + Cast(ACCT_NBR as varchar(20))) as acct,
I know this post is already answered and is correct. But would like to post the below answer because from SQL Server 2017 onwards, this is too easy and someoen might find this helpful in future.
CONCAT_WS(CHAR(10),Cast(NBR as varchar(20)) ,Cast(ACCT_NBR as varchar(20))) as acct
CHAR(10) can be for space in SQL SERVER. You can replace CHAR(10) with any separator you like to. For example,
CONCAT_WS(',',Cast(NBR as varchar(20)) ,Cast(ACCT_NBR as varchar(20))) as acct
the above query will add the separator ',' between each strings being concatenated.
If its an Oracle Database, try
NBR || ' ' || ACCT_NBR as acct
Stuff(Coalesce(', ' + [Address1], '') + Coalesce(', ' + [Address2], '') + Coalesce(', ' + [City], '') + Coalesce(', ' + [State], '') + Coalesce(', ' + [Country], '') +Coalesce('-' + [Zip], ''), 1, 1, '') AS [Address] FROM Customers
I know I'm 7 years late, but felt like I should give this a try.
(NBR +space(5) + ACCT_NBR) as acct
This will add 5 whitespaces between the 2 concatenated items.
My example on how I tested was as follows:
select
+ N'(Contactname: '+ contactname + space(5) + N'(Company_Name: ' + companyname + N')' + N'(Contact_Title: ' + contacttitle + N')'
from Sales.Customers
In Teradata SQL you can use the below. It will always pull the last 3 days.
WHERE create_ts BETWEEN (DATE -3 || ' ' || '00:00:00') AND (DATE -1 || ' ' || '23:59:59')

simplifying a LEFT / REPLACE query

I have a query that is in dire need of being simplified. Here is part of the query:
SELECT
LEFT(MLIS.REQUESTOR_FIRST_NAME, CharIndex( ' ', MLIS.REQUESTOR_FIRST_NAME + ' ' ) - 1)
, CharIndex( ' ', LEFT(MLIS.REQUESTOR_FIRST_NAME, CharIndex( ' ', MLIS.REQUESTOR_FIRST_NAME + ' ' ) - 1) + ' ' ) - 1)
+REPLICATE(' ',25),25)+
LEFT(' '+REPLICATE(' ',20),20)+
LEFT(
LEFT(
LEFT(MLIS.REQUESTOR_LAST_NAME, CharIndex( ',', MLIS.REQUESTOR_LAST_NAME + ',' ) - 1)
, CharIndex( ',', LEFT(MLIS.REQUESTOR_LAST_NAME, CharIndex( ',', MLIS.REQUESTOR_LAST_NAME + ',' ) - 1) + ',' ) - 1)
the reason I am doing the replicates is because i am building a fixed length string. each column needs to be a fixed length.
in addition to the above query, for every occurrence of MLIS.REQUESTOR_FIRST_NAME and MLIS.REQUESTOR_LAST_NAME i need to do:
REPLACE(REPLACE(MLIS.REQUESTOR_FIRST_NAME,', MD',''),',MD','')
and
REPLACE(REPLACE(MLIS.REQUESTOR_LAST_NAME,', MD',''),',MD','')
How do I include these REPLACES in the query and simplify the entire thing?
thanks so much for your guidance and kind help.
select the common bits in a subquery... (you'll have a bit more)
SELECT
LEFT(REQUESTOR_FIRST_NAME, fname_idx - 1)
, CharIndex( ' ', LEFT(MLIS.REQUESTOR_FIRST_NAME, fname_idx - 1) + ' ' ) - 1)
..
FROM ( select CharIndex( ' ', MLIS.REQUESTOR_FIRST_NAME + ' ' ) fname_idx, REQUESTOR_FIRST_NAME from...
Using a subquery will help with the syntax. In addition, you can cast to a CHAR() to pad and truncate strings to a given length.
I think the following does what you want:
SELECT cast(fname as char(25)) + ' ' + cast(lname as char(25))
from (select replace(replace(LEFT(MLIS.REQUESTOR_FIRST_NAME,
CharIndex(' ', MLIS.REQUESTOR_FIRST_NAME + ' ' ) - 1
),
',MD', ''),
', MD', '') as fname,
replace(relpace(left(MLIS.REQUESTOR_LAST_NAME,
CharIndex(',', MLIS.REQUESTOR_LAST_NAME + ',' ) - 1),
CharIndex(',', LEFT(MLIS.REQUESTOR_LAST_NAME,
CharIndex( ',', MLIS.REQUESTOR_LAST_NAME + ',' ) - 1) + ','
) - 1
),
',MD', ''),
', MD', '') as lname
However, it is hard to follow the original query, and there might be a syntax error. This query is meant to give you some guidance on solving the problem. I would also put a cast after the concatenate to be sure the final string is the right length.

Combine First, Middle Initial, Last name and Suffix in T-SQL (No extra spaces)

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