Concatenate and format text in SQL - 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.

Related

comma separated column values

I need to take the values from 3 columns and group them into 1 column as comma separated:
2014-01-01,2014-01-29
The problem is that one or more columns can be NULL and therefore it messes up the commas as such:
2014-01-01,,2014-01-29
This is how I have it coded (the case statement basically just strips out a comma if it's the last character in the string.
I need to add some logic so that it takes into account NULLs but I'm having a hard time coming up with it.
CASE WHEN RIGHT(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate, 1) = ','
THEN LEFT(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate, LEN(ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate) - 1)
ELSE ISNULL(d.FirstGapDate + ',', '') + ISNULL(d.PayrollGapDate + ',', '') + d.LastGapDate
END AS AlLGapDatesFormatted
EDIT -
I need to group the highlighted (notice that PayrollGapDate is ''):
And this is what I'm getting:
And this is the code I implemented:
try using this technique:
SET CONCAT_NULL_YIELDS_NULL ON --<<<make sure concatenations with NULL result in NULL
DECLARE #C1 varchar(10)='AAA'
,#C2 varchar(10)='BBB'
,#C3 varchar(10)=null
,#C4 varchar(10)='DDD'
SELECT STUFF( ISNULL(', '+#C1,'')
+ISNULL(', '+#C2,'')
+ISNULL(', '+#C3,'')
+ISNULL(', '+#C4,'')
,1,2,''
)
output:
-----------------------------------------------
AAA, BBB, DDD
(1 row(s) affected)
You let the ', '+#C3 result in NULL, which the ISNULL(***,'') converts to empty string. The STUFF(***,1,2,'') removes the leading comma and space.
try:
SELECT STUFF( ISNULL(', '+d.FirstGapDate,'')
+ISNULL(', '+d.PayrollGapDate,'')
+ISNULL(', '+d.LastGapDate,'')
,1,2,''
)
FROM ...
WHERE...
You can apply something like this above your expression to replace many commas with one comma:
declare #s varchar(100) = 'ABC,,,,DEF'
select replace(replace(replace(#s, ',', '[]'), '][', ''), '[]', ',')

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

Computed Column (COALESCE vs CASE vs ISNULL)

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.

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

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

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