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
-
SELECT LTRIM(RTRIM(LINE1)) + LTRIM(RTRIM(LINE2)) + LTRIM(RTRIM(LINE3)) AS MailAddress1, LTRIM(RTRIM(CITY)) + ' ' + LTRIM(RTRIM(STATE)) + ' ' + LTRIM(RTRIM(POSTALCODE)) AS MailAddress2 FROM MyTableJulian Aubourg : Not exactly what's being asked for ;)Gerhard Weiss : That is correct. I would like to have four separate output fields.Mark Brittingham : Right - this one is not correct. -
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 @addressResult:
123 Some Address Royal Oak MI 45673-2312Fiddle with the control characters until you get the result you need.
DJ : I think the OP wants four separate output fields.Gerhard Weiss : That is correct. I would like to have four separate output fields.Rob Garrison : Do you need this to be set-based, or are you calling a function or stored procedure per-address?Gerhard Weiss : set-based but they are calling a table-value function to get the active address (we keep a history of all address for one person.)Gerhard Weiss : I do not know why they are using 4 output fields. This is being used in a Aspose Word Merge and I bet one output field would have probably worked with the code Rob supplied. I will have to ask the Aspose developer.Rob Garrison : Using four output fields will make the SQL much more complex. If you can handle it with the simple query above (plus RTRIM/LTRIM), it will be much simpler to maintain. -
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 RNHere'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 AddrTableAnd 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 pvtThis returns:
Addr1 Addr2 Addr3 Addr4 -------------- ------------------ ------------- ------------------ Address1 Westby WI 54667Mark Brittingham : This will give you as many records as are found...does it need to be four? There is a way to do that as well.Mark Brittingham : Also, do you need this for a specific record? E.g. ClientID=1234Gerhard Weiss : Yes to both questions Mark.Mark Brittingham : Ok, example two chooses the records for just the given ClientID (unique identifier). Let me cook up a version with four records. I take it that you just want the records returned (not the "MailAddressX="). Is this right or do you need the descriptor?Gerhard Weiss : No desciptor is needed. Just the address information.Mark Brittingham : Dayam - just did the descriptor. Oh well, that makes it easier to return four lines...Mark Brittingham : Although the first solution did let me use the cool new "Row_Number() over (Order by FieldName)" construct.Mark Brittingham : Actually, once I realized that the four fields gave me the four output rows, the Row_Number() stays. I changed my fields to your fields so the only thing you should have to do is to change the table name. Note, too, that this does return the row number as well as the address.Portman : I wish I had more than one vote to give. Well played, sir.Mark Brittingham : Thank you PortmanMark Brittingham : Gerhard - I updated your query a bit and, in so doing, realized that you needed columns rather than rows. Easy enough, I updated the answer as well to provide columns.Gerhard Weiss : @Mark Brittingham, I am going to give you the SQL Stud badge.Mark Brittingham : Lol - I do tend to do best with SQL questions here on SO.
0 comments:
Post a Comment