Sybase SQL - null condition, removing whitespace - sql

I've got this query below that drove me mad, would you be able to fix the code below so that the result will be like this : "123 Bridge St 2500" instead of " 123 Bridge St 2500" (extra whitespace at the beginning and in between St and 2500)?
declare #street varchar(20), #street2 varchar(20), #suburb varchar(20), #postcode varchar(4)
set #street = null
set #street2 = '123 Bridge St'
set #suburb = null
set #postcode = '2500'
select address = case #street when null then '' else #street + ' ' end
+case #street2 when null then '' else #street2 + ' ' end
+case #suburb when null then '' else #suburb + ' ' end
+case #postcode when null then '' else #postcode + ' ' end
-- Expected Result: '123 Bridge St 2500'
-- Actual Result: ' 123 Bridge St 2500'
Thanks!

Try
select case when #street is null then '' else #street + ' ' end
+case when #street2 is null then '' else #street2 + ' ' end
+case when #suburb is null then '' else #suburb + ' ' end
+case when #postcode is null then '' else #postcode + ' ' end
When you write case #street when null.. that's the same as when #street = null which doesn't work, so use is null instead.

Thanks for all your comments,
here's the solution that worked
select address = ltrim(rtrim(#street) + ' ') + ltrim(rtrim(#street2) + ' ') + ltrim(rtrim(#suburb) + ' ') + #postcode

Related

Filter data by keywords and note where they were found

so i have a query at the moment.
SELECT *
FROM TABLE1
It yields besides other stuff 4 colums which contain text "Textbox1" "Textbox2" "Textbox3" "Textbox4".
I now want to filter this query by keywords in those text boxes. Basically the user can enters 0 to 5 keywords and the rows from TABLE1 should only show if at least one keyword was found in one of the textboxes. Also a new column should be added that for every keyword that was found in a textbox should say which keyword and in which textboxes it was found.
The query itself will later run in SSRS which is where the user puts in the keywords. So the keywords are accasable as varchars. For the query you can use this:
DECLARE #Keyword1 AS VARCHAR(100) = '';
DECLARE #Keyword2 AS VARCHAR(100) = '';
DECLARE #Keyword3 AS VARCHAR(100) = '';
DECLARE #Keyword4 AS VARCHAR(100) = '';
DECLARE #Keyword5 AS VARCHAR(100) = '';
Thanks for any help.
Edit:
This is a very unelegant solution and it's not exactly what you wanted but hopefully close enough.
To improve it, especially if you are goning to extend this to more column/keywords I would consider unpivoting the data, testing each row and then aggregating the result of that back up again.
DECLARE #t TABLE (T1 varchar(100), T2 varchar(100), T3 varchar(100), T4 varchar(100))
INSERT INTO #t VALUES
(1, 11, 203, 30),
(8898, 54452, 1222, 12122)
DECLARE #k1 varchar(100) = '1'
DECLARE #k2 varchar(100) = '22'
SET #k1 = '%' + #k1 + '%'
SET #k2 = '%' + #k2 + '%'
SELECT
*
, CASE WHEN T1 like #k1 THEN '1:T1 ' ELSE '' END +
CASE WHEN T2 like #k1 THEN '1:T2 ' ELSE '' END +
CASE WHEN T3 like #k1 THEN '1:T3 ' ELSE '' END +
CASE WHEN T4 like #k1 THEN '1:T4 ' ELSE '' END +
CASE WHEN T1 like #k2 THEN '2:T1 ' ELSE '' END +
CASE WHEN T2 like #k2 THEN '2:T2 ' ELSE '' END +
CASE WHEN T3 like #k2 THEN '2:T3 ' ELSE '' END +
CASE WHEN T4 like #k2 THEN '2:T4 ' ELSE '' END
As Found
FROM #t
This give the following results.
With the help of Alan Schofield i found the solution that i need.
SELECT * from( Select*,
CASE WHEN Textbox1 like '%'+#Keyword1+'%' AND #Keyword1 <> '' THEN #Keyword1 +', ' ELSE '' END +
CASE WHEN Textbox1 like '%'+#Keyword2+'%' AND #Keyword2 <> '' THEN #Keyword2 +', ' ELSE '' END +
CASE WHEN Textbox1 like '%'+#Keyword3+'%' AND #Keyword3 <> '' THEN #Keyword3 +', ' ELSE '' END +
CASE WHEN Textbox1 like '%'+#Keyword4+'%' AND #Keyword4 <> '' THEN #Keyword4 +', ' ELSE '' END +
CASE WHEN Textbox1 like '%'+#Keyword5+'%' AND #Keyword5 <> '' THEN #Keyword5 +', ' ELSE '' END
As Textbox1found,
CASE WHEN Textbox2 like '%'+#Keyword1+'%' AND #Keyword1 <> '' THEN #Keyword1 +', ' ELSE '' END +
CASE WHEN Textbox2 like '%'+#Keyword2+'%' AND #Keyword2 <> '' THEN #Keyword2 +', ' ELSE '' END +
CASE WHEN Textbox2 like '%'+#Keyword3+'%' AND #Keyword3 <> '' THEN #Keyword3 +', ' ELSE '' END +
CASE WHEN Textbox2 like '%'+#Keyword4+'%' AND #Keyword4 <> '' THEN #Keyword4 +', ' ELSE '' END +
CASE WHEN Textbox2 like '%'+#Keyword5+'%' AND #Keyword5 <> '' THEN #Keyword5 +', ' ELSE '' END
As Textbox2found,
CASE WHEN Textbox3 like '%'+#Keyword1+'%' AND #Keyword1 <> '' THEN #Keyword1 +', ' ELSE '' END +
CASE WHEN Textbox3 like '%'+#Keyword2+'%' AND #Keyword2 <> '' THEN #Keyword2 +', ' ELSE '' END +
CASE WHEN Textbox3 like '%'+#Keyword3+'%' AND #Keyword3 <> '' THEN #Keyword3 +', ' ELSE '' END +
CASE WHEN Textbox3 like '%'+#Keyword4+'%' AND #Keyword4 <> '' THEN #Keyword4 +', ' ELSE '' END +
CASE WHEN Textbox3 like '%'+#Keyword5+'%' AND #Keyword5 <> '' THEN #Keyword5 +', ' ELSE '' END
As Textbox3found,
CASE WHEN Textbox4 like '%'+#Keyword1+'%' AND #Keyword1 <> '' THEN #Keyword1 +', ' ELSE '' END +
CASE WHEN Textbox4 like '%'+#Keyword2+'%' AND #Keyword2 <> '' THEN #Keyword2 +', ' ELSE '' END +
CASE WHEN Textbox4 like '%'+#Keyword3+'%' AND #Keyword3 <> '' THEN #Keyword3 +', ' ELSE '' END +
CASE WHEN Textbox4 like '%'+#Keyword4+'%' AND #Keyword4 <> '' THEN #Keyword4 +', ' ELSE '' END +
CASE WHEN Textbox4 like '%'+#Keyword5+'%' AND #Keyword5 <> '' THEN #Keyword5 +', ' ELSE '' END
AS Textbox4found
FROM Table1)as Result
WHERE Result.Textbox1found <> '' OR Result.Textbox2found <> '' OR Result.Textbox3found <> '' OR Result.Textbox4found <> '' or (#Keyword1='' AND #Keyword2='' AND #Keyword3='' AND #Keyword4='' AND #Keyword5='')
I switched to a Textbox based query which will generat for every textbox a column with the keywords found in that textbox.

SQL: Query stored in #query keeps trying to convert to data type INT

I don't know why my code is trying to convert the query within the variable to data type INT. And what's even stranger is that I got the code working fine on Linqpad. Then I pasted the code into Report Builder 3.0 and tested it again within the query view, which worked fine. Next, I went to report view and ran it once. This worked fine as well. However, once I ran it a second time with a new specified parameter, it threw an error and told me to check on the local machine.
The code:
DECLARE #item varchar(50) = '%'
DECLARE #lp varchar(50) = '1231888'
DECLARE #loc varchar(10) = '%'
DECLARE #lot varchar(30) = '%'
DECLARE #trans_type varchar(2) = '%'
DECLARE #desc varchar(20) = '%'
DECLARE #whse varchar(4) = '%'
DECLARE #u_m varchar(20) = '%'
DECLARE #emp_num varchar(20) = '%'
DECLARE #ref_num varchar(20) = '%'
DECLARE #fglot varchar(20) = '%'
DECLARE #shift varchar(20) = '%'
DECLARE #truckid varchar(20) = '%'
DECLARE #trans_date datetime2 = NULL
DECLARE #trans_date_string varchar(10) = CAST(#trans_date AS nvarchar(10))
DECLARE #shiftdate datetime2 = NULL
DECLARE #shiftdate_string varchar(10) = CAST(#shiftdate AS nvarchar(10))
DECLARE #createdate datetime2 = NULL
DECLARE #createdate_string varchar(19) = CAST(#createdate AS nvarchar(19))
DECLARE #ref_line_suf int = 4
DECLARE #ref_line_suf_string varchar(2) = CAST(#ref_line_suf AS varchar(2))
DECLARE #qty decimal = NULL
DECLARE #qty_string varchar(30) = CAST(#qty AS varchar(30))
--Define query
DECLARE #query as nvarchar(2500)
SET #query =
'SELECT TOP (10000)
*
FROM
isw_lptrans AS t
WHERE
1=1'
+ CASE
WHEN #item = '%' OR #item = ''
THEN ''
ELSE ' AND t.item LIKE ' + '''' + #item + ''''
END
+ CASE
WHEN #lp = '%' OR #lp = ''
THEN ''
ELSE ' AND t.lp_num LIKE ' + '''' + '%' + #lp + '%' + ''''
END
+ CASE
WHEN #loc = '%' OR #loc = ''
THEN ''
ELSE ' AND t.loc = ' + '''' + #loc + ''''
END
+ CASE
WHEN #lot = '%' OR #lot = ''
THEN ''
ELSE ' AND t.lot = ' + '''' + #lot + ''''
END
+ CASE
WHEN #trans_type = '%' OR #trans_type = ''
THEN ''
ELSE ' AND t.trans_type = ' + '''' + #trans_type + ''''
END
+ CASE
WHEN #desc = '%' OR #desc = ''
THEN ''
ELSE ' AND t.description LIKE ' + '''' + '%' + #desc + '%' + ''''
END
+ CASE
WHEN #whse = '%' OR #whse = ''
THEN ''
ELSE ' AND t.whse = ' + '''' + #whse + ''''
END
+ CASE
WHEN #u_m = '%' OR #u_m = ''
THEN ''
ELSE ' AND t.u_m = ' + '''' + #u_m + ''''
END
+ CASE
WHEN #emp_num = '%' OR #emp_num = ''
THEN ''
ELSE ' AND t.emp_num = ' + '''' + #emp_num + ''''
END
+ CASE
WHEN #ref_num = '%' OR #ref_num = ''
THEN ''
ELSE ' AND t.ref_num = ' + '''' + #ref_num + ''''
END
+ CASE
WHEN #fglot = '%' OR #fglot = ''
THEN ''
ELSE ' AND t.fglotcode = ' + '''' + #fglot + ''''
END
+ CASE
WHEN #shift = '%' OR #shift = ''
THEN ''
ELSE ' AND t.uf_shift = ' + '''' + #shift + ''''
END
+ CASE
WHEN #truckid = '%' OR #truckid = ''
THEN ''
ELSE ' AND t.uf_truckid = ' + '''' + #truckid + ''''
END
+ CASE
WHEN #trans_date IS NULL
THEN ''
ELSE ' AND t.trans_date = ' + '''' + #trans_date_string + ''''
END
+ CASE
WHEN #shiftdate IS NULL
THEN ''
ELSE ' AND t.uf_shift_start_date = ' + '''' + #shiftdate_string + ''''
END
+ CASE
WHEN #createdate IS NULL
THEN ''
ELSE ' AND (t.createdate BETWEEN ' + '''' + CAST(DATEADD(hh, -24, #createdate) AS varchar(19)) + '''' + ' AND ' + '''' + CAST(DATEADD(hh, 24, #createdate) AS varchar(19)) + '''' + ' ) '
END
+ CASE
WHEN #ref_line_suf IS NULL
THEN ''
ELSE ' AND t.ref_line_suf = ' + #ref_line_suf_string
END
+ CASE
WHEN #qty IS NULL
THEN ''
ELSE ' AND t.qty = ' + #qty_string
END
;
print #query
EXEC sp_executesql #query
Screenshot of error:
Query print-out with the parameters that create a problem (note: this is from Linqpad, where there is no problem. The problem occurs in Report Builder 3.0):
SELECT TOP (10000)
*
FROM
isw_lptrans AS t
WHERE
1=1 AND t.lp_num LIKE '%1231888%' AND t.ref_line_suf = 4
This should work for 2008 now.
DECLARE #item varchar(50) = '1'
DECLARE #lp varchar(50) = '1231888'
DECLARE #loc varchar(10) = '2'
DECLARE #lot varchar(30) = '3'
DECLARE #trans_type varchar(2) = '4'
DECLARE #desc varchar(20) = '5'
DECLARE #whse varchar(4) = '6'
DECLARE #u_m varchar(20) = '7'
DECLARE #emp_num varchar(20) = '8'
DECLARE #ref_num varchar(20) = '9'
DECLARE #fglot varchar(20) = '10'
DECLARE #shift varchar(20) = '11'
DECLARE #truckid varchar(20) = '12'
DECLARE #trans_date datetime2 = '2015-01-01'
DECLARE #shiftdate datetime2 = '2015-01-01'
DECLARE #createdate datetime2 = '2015-01-01'
DECLARE #ref_line_suf int = 4
DECLARE #qty decimal(15,5) = 5.2678
--Define query
DECLARE #query NVARCHAR(MAX)
SET #query =
'SELECT TOP (10000)
*
FROM isw_lptrans AS t
WHERE 1=1'
;
SET #query =
#query
+ISNULL(' AND t.item LIKE '''+CASE WHEN #item IN ('','%') THEN NULL ELSE #item END+'''','')
+ISNULL(' AND t.lp LIKE ''%'+CASE WHEN #lp IN ('','%') THEN NULL ELSE #lp END+'%''','')
+ISNULL(' AND t.loc = '''+CASE WHEN #loc IN ('','%') THEN NULL ELSE #loc END+'''','')
+ISNULL(' AND t.lot = '''+CASE WHEN #lot IN ('','%') THEN NULL ELSE #lot END+'''','')
+ISNULL(' AND t.trans_type = '''+CASE WHEN #trans_type IN ('','%') THEN NULL ELSE #trans_type END+'''','')
+ISNULL(' AND t.desc LIKE ''%'+CASE WHEN #desc IN ('','%') THEN NULL ELSE #desc END+'%''','')
+ISNULL(' AND t.whse = '''+CASE WHEN #whse IN ('','%') THEN NULL ELSE #whse END+'''','')
+ISNULL(' AND t.u_m = '''+CASE WHEN #u_m IN ('','%') THEN NULL ELSE #u_m END+'''','')
+ISNULL(' AND t.emp_num = '''+CASE WHEN #emp_num IN ('','%') THEN NULL ELSE #emp_num END+'''','')
+ISNULL(' AND t.ref_num = '''+CASE WHEN #ref_num IN ('','%') THEN NULL ELSE #ref_num END+'''','')
+ISNULL(' AND t.fglot = '''+CASE WHEN #fglot IN ('','%') THEN NULL ELSE #fglot END+'''','')
+ISNULL(' AND t.shift = '''+CASE WHEN #shift IN ('','%') THEN NULL ELSE #shift END+'''','')
+ISNULL(' AND t.truckid = '''+CASE WHEN #truckid IN ('','%') THEN NULL ELSE #truckid END+'''','')
+ISNULL(' AND t.trans_date = '''+CONVERT(VARCHAR(10),#trans_date)+'''','')
+ISNULL(' AND t.uf_shift_start_date = '''+CONVERT(VARCHAR(10),#shiftdate)+'''','')
+ISNULL(' AND t.createdate BETWEEN '''+CONVERT(VARCHAR(19),DATEADD(hour,-24,#createdate))+''' AND '''+CONVERT(VARCHAR(19),DATEADD(hour,24,#createdate))+'''','')
+ISNULL(' AND t.ref_line_suf = '+CONVERT(VARCHAR(2),#ref_line_suf),'')
+ISNULL(' AND t.qty = '+CONVERT(VARCHAR(30),#qty)+'''','')
;
print #query;

Function Within a View SQL Server Management Studio

Hey I am having a problem with a View I am trying to create I am trying to get the Full Address of a member be Displayed in correlation with the MemberID of my Member Table along with a few other fields in other tables but the FullAddress and MFullAddress are both coming up as NULL Values and I am not sure why hope someone can help. Below is the Code for my View.
SELECT dbo.Member.MemberID, dbo.Member.Title + ' ' + dbo.Member.Forename + ' ' + dbo.Member.Surname AS Fullname, dbo.GetMemberFullAddress(dbo.Member.MemberID) AS FullAddress,
dbo.GetMemberFullMailingAddress(dbo.Member.MemberID) AS MFullAddress, dbo.Lookup_ActionType.Description, dbo.Payment.Amount
FROM dbo.Payment RIGHT OUTER JOIN
dbo.Member ON dbo.Payment.PaymentID = dbo.Member.MemberID RIGHT OUTER JOIN
dbo.Action LEFT OUTER JOIN
dbo.Lookup_ActionType ON dbo.Action.ActionTypeID = dbo.Lookup_ActionType.ActionTypeID ON dbo.Member.MemberID = dbo.Action.MemberID
WHERE (dbo.Member.MemberID = dbo.Member.MemberID)
And here are Both of my Functions Called dbo.GetFullMemberAddress The Mfulladdress function is the same only different fields
USE [ICOM.Database]
GO
/****** Object: UserDefinedFunction [dbo].[GetMemberFullAddress] Script Date: 22/10/2014 11:53:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Richard Glass>
-- Create date: <22/10/2014>
-- Description: <Returns Full Address>
-- =============================================
ALTER FUNCTION [dbo].[GetMemberFullAddress]
-- Add the parameters for the function here
(#MemberID as integer)
RETURNS varchar(250)
AS
BEGIN
DECLARE #AddressLine as varchar(40)
DECLARE #FullAddress as varchar(250)
SET #FullAddress = (SELECT LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) AS FullName FROM Member WHERE MemberID = #MemberID) + CHAR(10)
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
SET #AddressLine = (SELECT Member.AddressLine1 FROM Member WHERE MemberID = #MemberID)
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
SET #AddressLine = (SELECT AddressLine2 FROM Member WHERE MemberID = #MemberID)
IF #AddressLine <> ''
BEGIN
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
END
SET #AddressLine = (SELECT AddressLine3 FROM Member WHERE MemberID = #MemberID)
IF #AddressLine <> ''
BEGIN
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
END
SET #AddressLine = (SELECT Town FROM Member WHERE MemberID = #MemberID)
IF #AddressLine <> ''
BEGIN
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
END
SET #AddressLine = (SELECT PostCode FROM Member WHERE MemberID = #MemberID)
SET #FullAddress = #FullAddress + #AddressLine
RETURN #FullAddress
END
AND
The problem is because concatenetating NULL with anything yields NULL by default. At the start of the function you have:
DECLARE #AddressLine as varchar(40)
DECLARE #FullAddress as varchar(250)
SET #FullAddress = (SELECT LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) AS FullName FROM Member WHERE MemberID = #MemberID) + CHAR(10)
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
And the problem line is:
SET #FullAddress = #FullAddress + #AddressLine + CHAR(10)
At this point #AddressLine is NULL, therefore you set #FullAddress to NULL.
You can get your full address though in a much less convoluted fashion, something like:
(LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) + ',' +
CASE WHEN ISNULL(AddressLine1, '') = '' THEN '' ELSE AddressLine1 + ',' END +
CASE WHEN ISNULL(AddressLine2, '') = '' THEN '' ELSE AddressLine2 + ',' END +
CASE WHEN ISNULL(AddressLine3, '') = '' THEN '' ELSE AddressLine3 + ',' END +
CASE WHEN ISNULL(Town, '') = '' THEN '' ELSE Town + ',' END +
CASE WHEN ISNULL(PostCode, '') = '' THEN '' ELSE PostCode END
Although seemingly quite verbose, it does not require repeatedly querying the member table. You could then just add this as a computed column:
I would be inclined to add MemberAddress as a computed column to dbo.Member though, something like:
ALTER TABLE dbo.Member
ADD MemberAddress AS
(LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname) + ',' +
CASE WHEN ISNULL(AddressLine1, '') = '' THEN '' ELSE AddressLine1 + ',' END +
CASE WHEN ISNULL(AddressLine2, '') = '' THEN '' ELSE AddressLine2 + ',' END +
CASE WHEN ISNULL(AddressLine3, '') = '' THEN '' ELSE AddressLine3 + ',' END +
CASE WHEN ISNULL(Town, '') = '' THEN '' ELSE Town + ',' END +
CASE WHEN ISNULL(PostCode, '') = '' THEN '' ELSE PostCode END;
Would your stored proc be better if the code was just this?
DECLARE #FullAddress as varchar(250)
SELECT FullAddress = LTRIM(ISNULL(Title + ' ', '') + ForeName + ' ' + Surname)
+ CHAR(10)
+ ISNULL(Member.AddressLine1 + CHAR(10),'')
+ ISNULL(Member.AddressLine2 + CHAR(10),'')
+ ISNULL(Member.AddressLine3 + CHAR(10),'')
+ ISNULL(Member.Town + CHAR(10),'')
+ ISNULL(Member.PostCode + CHAR(10),'')
FROM Member
WHERE MemberID = #MemberID
RETURN #FullAddress

SQL Server Conditional Mailing Address Formatting

I have the following SQL to format a US address into each line for a mailing address but it is rather ugly. Is there a better way to solve this problem or does it have to be this ugly? Also, the problem with this code is that it always ends up with an extra new line at the end.
declare #NL varchar(2);
set #NL = char(13) + char(10);
select
case when rtrim(coalesce(AttentionLine,'') ) != '' then rtrim(AttentionLine ) + #NL else '' end
+ case when rtrim(coalesce(Recipient,'') ) != '' then rtrim(Recipient ) + #NL else '' end
+ case when rtrim(coalesce(AddlAddrLine,'') ) != '' then rtrim(AddlAddrLine ) + #NL else '' end
+ case when rtrim(coalesce(DeliveryAddr,'') ) != '' then rtrim(DeliveryAddr ) + #NL else '' end
+ case when rtrim(coalesce(LastLine,'') ) != '' then rtrim(LastLine ) + #NL else '' end
+ case when rtrim(coalesce(Country,'') ) != '' then rtrim(Country ) + #NL else '' end
as FormattedMailingAddress
from Address
where Id = 1
If your Sql Server Settings are such that NULL + varchar returns NULL (SET CONCAT_NULL_YIELDS_NULL (Transact-SQL)), this can help.
DECLARE #Address TABLE(
ID INT,
AttentionLine VARCHAR(50),
Recipient VARCHAR(50),
AddlAddrLine VARCHAR(50),
DeliveryAddr VARCHAR(50),
LastLine VARCHAR(50),
Country VARCHAR(50)
)
declare #NL varchar(2);
set #NL = char(13) + char(10);
INSERT INTO #Address SELECT 1, NULL, '1', NULL, '2', NULL, '3'
select
case when rtrim(coalesce(AttentionLine,'') ) != '' then rtrim(AttentionLine ) + #NL else '' end
+ case when rtrim(coalesce(Recipient,'') ) != '' then rtrim(Recipient ) + #NL else '' end
+ case when rtrim(coalesce(AddlAddrLine,'') ) != '' then rtrim(AddlAddrLine ) + #NL else '' end
+ case when rtrim(coalesce(DeliveryAddr,'') ) != '' then rtrim(DeliveryAddr ) + #NL else '' end
+ case when rtrim(coalesce(LastLine,'') ) != '' then rtrim(LastLine ) + #NL else '' end
+ case when rtrim(coalesce(Country,'') ) != '' then rtrim(Country ) + #NL else '' end
as FormattedMailingAddress ,
RTRIM(coalesce(AttentionLine + #NL,'')) +
RTRIM(coalesce(Recipient + #NL,'')) +
RTRIM(coalesce(AddlAddrLine + #NL,'')) +
RTRIM(coalesce(DeliveryAddr + #NL,'')) +
RTRIM(coalesce(LastLine + #NL,'')) +
RTRIM(coalesce(Country + #NL,''))
from #Address
where Id = 1
I realize this is an old question, but there is a new solution to this problem: the CONCAT_WS() function, which is new for SQL Server 2017 (it's also available for Azure SQL Database).
SELECT CONCAT_WS (
CHAR(13) + CHAR(10), --Separator
NULLIF(AttentionLine, ''),
NULLIF(Recipient, ''),
NULLIF(AddlAddrLine, ''),
NULLIF(DeliveryAddr, ''),
NULLIF(LastLine, ''),
NULLIF(Country, '')
)
AS FormattedMailingAddress
FROM Address
WHERE Id = 1
NULL values are ignored by the function, which is why NULLIF is used with each argument/parameter in this example. (When the argument/parameter evaluates to NULL, the separator won't be added either). Here's a short blog post with some more details: New For SQL Server 2017: T-SQL Function CONCAT_WS

How can I improve this Mailing Address SQL Server SELECT Statement?

How can I format a Mailing Address so that I always push all non-null rows to the top? That is, I want to convert an address from the structure below to a mailing address.
Here is the structure:
[Line1] [varchar](50) NULL,
[Line2] [varchar](50) NULL,
[Line3] [varchar](50) NULL,
[City] [varchar](50) NULL,
[State] [varchar] (2) NULL,
[PostalCode] [varchar](50) NULL,
Here is some sample data:
Line1=
Line2=123 Some Address
Line3=
City=Royal Oak
State=MI
ZIP=45673-2312
Here is what the result should look like (4 distinct or separate fields should be returned):
MailAddress1=123 Some Address
MailAddress2=ROYAL OAK MI 45673-2312
MailAddress3=
MailAddress4=
I am using SQL Server 2005.
Someone wrote this logic in our company and it just seemed to complex (Note: this is not the whole SELECT statement):
,CASE
WHEN eai.Line1 IS NULL OR eai.Line1 = '' THEN
CASE
WHEN eai.Line2 IS NULL OR eai.Line2 = '' THEN
CASE
WHEN eai.Line3 IS NULL OR eai.Line3 = '' THEN ISNULL(LTRIM(RTRIM(eai.City)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.PostalCode)),'')
ELSE eai.Line3
END
ELSE eai.Line2
END
ELSE eai.Line1
END
,CASE
WHEN eai.Line1 IS NULL OR eai.Line1 = '' THEN
CASE
WHEN eai.Line3 IS NULL OR eai.Line3 = '' THEN ISNULL(LTRIM(RTRIM(eai.City)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.PostalCode)),'')
ELSE eai.Line3
END
ELSE
CASE
WHEN eai.Line2 IS NULL OR eai.Line2 = '' THEN
CASE
WHEN eai.Line3 IS NULL OR eai.Line3 = '' THEN ISNULL(LTRIM(RTRIM(eai.City)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.PostalCode)),'')
ELSE eai.Line3
END
ELSE eai.Line2
END
END
,CASE
WHEN eai.Line1 IS NULL OR eai.Line1 = '' THEN
CASE
WHEN eai.Line2 IS NULL OR eai.Line2 = '' THEN NULL
ELSE
CASE
WHEN eai.Line3 IS NULL OR eai.Line3 = '' THEN NULL
ELSE ISNULL(LTRIM(RTRIM(eai.City)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.PostalCode)),'')
END
END
ELSE
CASE
WHEN eai.Line2 IS NULL OR eai.Line2 = '' THEN
CASE
WHEN eai.Line3 IS NULL OR eai.Line3 = '' THEN NULL
ELSE ISNULL(LTRIM(RTRIM(eai.City)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.PostalCode)),'')
END
ELSE
CASE
WHEN eai.Line3 IS NULL OR eai.Line3 = '' THEN ISNULL(LTRIM(RTRIM(eai.City)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(eai.PostalCode)),'')
ELSE eai.Line3
END
END
END
,CASE WHEN eai.Line2 IS NOT NULL AND eai.Line2 <> '' AND eai.Line3 IS NOT NULL AND eai.Line3 <> '' THEN eai.City + ' ' + eai.RegionCode + ' ' + eai.PostalCode ELSE NULL END
The way to do this is with an UNPIVOT. Here is the solution:
With AddrTable as (
Select AddrFld, MailAddr From (
Select Cast(ISNULL([Line1], '') as Varchar(102)) as [A1],
Cast(ISNULL([Line2], '') as Varchar(102)) as [A2],
Cast(ISNULL([Line3], '') as Varchar(102)) as [A3],
Cast(ISNULL(LTRIM(RTRIM(City)),'') + ' ' + ISNULL(LTRIM(RTRIM(RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(PostalCode)),'') as Varchar(102)) as A4
From TableName Where UniqueID=#UniqueID) p
Unpivot (MailAddr For AddrFld in ([A1], [A2], [A3], [A4])) as unpvt)
Select Row_Number() over (Order by (Case Len(MailAddr) When 0 then 1 else 0 end), AddrFld) as RN,
MailAddr From AddrTable
Order By RN
Here's the output:
Address1
Westby WI 55555
-empty line-
-empty line-
Note that I had to use "Varchar(102)" as the field length (unpivot requires that all fields be the same) because your City/Region/Postal can have up to 102 chars in total. Also, note that "#UniqueID" is the identifier for the record whose address you need. This returns four and always four rows containing the data you need for your address.
UPDATE: If you need to return this as a set of four columns rather than four rows, then just plop it into a view and then query the view with a Pivot. I've included the view here for completeness as I had to change the above just a bit when creating the view so the uniqueID field was included and no sort was done (the sort is now done in the query):
Create View AddressRows AS
With AddrTable as (
Select UniqueID, AddrFld, MailAddr From (
Select UniqueID,
Cast(ISNULL([Line1], '') as Varchar(102)) as [A1],
Cast(ISNULL([Line2], '') as Varchar(102)) as [A2],
Cast(ISNULL([Line3], '') as Varchar(102)) as [A3],
Cast(ISNULL(LTRIM(RTRIM(City)),'') + ' ' + ISNULL(LTRIM(RTRIM(RegionCode)),'') + ' ' + ISNULL(LTRIM(RTRIM(PostalCode)),'') as Varchar(102)) as A4
From TableName Where UniqueID=#UniqueID) p
Unpivot (MailAddr For AddrFld in ([A1], [A2], [A3], [A4])) as unpvt)
Select UniqueID,
Row_Number() over (Order by (Case Len(MailAddr) When 0 then 1 else 0 end), AddrFld) as RN,
MailAddr From AddrTable
And then, when you want to pull your matching "row" out, Pivot it back using this SQL (notice that I am querying again using UniqueID):
Select [Addr1], [Addr2], [Addr3], [Addr4] From (
Select Top 4 'Addr' + Cast(Row_Number() over (Order by RN) as Varchar(12)) as AddrCol, -- "Top 4" needed so we can sneak the "Order By" in
MailAddr
From AddressRows Where UniqueID=#UniqueID
) p PIVOT (Max([MailAddr]) for AddrCol in ([Addr1], [Addr2], [Addr3], [Addr4])
) as pvt
This returns:
Addr1 Addr2 Addr3 Addr4
-------------- ------------------ ------------- ------------------
Address1 Westby WI 54667
Here's a three-minutes-invested solution:
DECLARE #address TABLE (
[Line1] [varchar](50) NULL,
[Line2] [varchar](50) NULL,
[Line3] [varchar](50) NULL,
[City] [varchar](50) NULL,
[State] [varchar] (2) NULL,
[PostalCode] [varchar](50) NULL
)
INSERT INTO #address (
[Line1],
[Line2],
[Line3],
[City],
[State],
[PostalCode]
)
VALUES (
NULL,
'123 Some Address',
NULL,
'Royal Oak',
'MI',
'45673-2312'
)
SELECT * FROM #address
SELECT
ISNULL(Line1 + CHAR(13), '')
+ ISNULL(Line2 + CHAR(13), '')
+ ISNULL(Line3 + CHAR(13), '')
+ ISNULL(City + ' ', '')
+ ISNULL([State] + ' ', '')
+ ISNULL(PostalCode, '')
FROM #address
Result:
123 Some Address
Royal Oak MI 45673-2312
Fiddle with the control characters until you get the result you need.
SELECT
LTRIM(RTRIM(LINE1)) + LTRIM(RTRIM(LINE2)) + LTRIM(RTRIM(LINE3)) AS MailAddress1,
LTRIM(RTRIM(CITY)) + ' ' + LTRIM(RTRIM(STATE)) + ' ' + LTRIM(RTRIM(POSTALCODE)) AS MailAddress2
FROM MyTable