我想将地址(Line1,Line2,Line3,City,State,ZIP)转换为没有空行并且城市,州和ZIP连接在一起的邮件地址(Addr1,Addr2,Addr3,Addr4)在一条线上。有一个功能这样做会非常好。
即。
线路1 =
Line2 = 123某处
3号线=
市=底特律
国家= MI
Zip = 48000
以下是传入地址的表格结构:
IF OBJECT_ID('tempdb..#Employee') IS NOT NULL DROP TABLE #Employee
CREATE TABLE #Employee (Line1 VARCHAR(30), Line2 VARCHAR(30), Line3 VARCHAR(30),
City VARCHAR(17), State VARCHAR(2), ZIP VARCHAR(10))
GO
INSERT #Employee VALUES ('', '123 Somewhere', '', 'Detroit', 'MI', '48000')
SELECT * FROM #Employee
生成的邮寄地址
Addr1 = 123某处
Addr2 =底特律MI 48000
ADDR3 =
Addr4 =
或一个 cr 字符的字段
地址=
123某处 cr
底特律MI 48000 cr
的 CR
cr
一个函数可以很好地返回Addr1,Addr2,Addr3和Addr4,或者只返回Addr。
SqueezeAddress(Line1,Line2,Line3,City,State,ZIP)
然后SqueezeAddress将返回Addr1,Addr2,Addr3,Addr4
或
地址为
所有Addr1-4行都是VARCHAR(40)或者如果使用一个字段Addr VARCHAR(200)
Per Phil在下面的评论中提出的请求,这是当前使用的逻辑(删除了许多字段以便于阅读):
SELECT Line1, Line2, Line3,
ISNULL(LTRIM(RTRIM(ADDR.City)) + ', ','') + ISNULL(ADDR.RegionCode,'')
+ ' ' + ISNULL(ADDR.PostalCode,'') AS Line4,
UPDATE #tmpBilling
SET Line1 = Line2, Line2 = NULL
WHERE ISNULL(Line1, '') = ''
AND ISNULL(Line2, '') <> ''
UPDATE #tmpBilling
SET Line2 = Line3, Line3 = NULL
WHERE ISNULL(Line2, '') = ''
AND ISNULL(Line3, '') <> ''
UPDATE #tmpBilling
SET Line2 = Line4, Line4 = NULL
WHERE ISNULL(Line2, '') = ''
AND ISNULL(Line4, '') <> ''
UPDATE #tmpBilling
SET Line3 = Line4, Line4 = NULL
WHERE ISNULL(Line3, '') = ''
AND ISNULL(Line2, '') <> ''
答案 0 :(得分:3)
我可能在这里遗漏了一些东西,但如果这只是简单的字符串连接,那么这将有效......
设置测试数据(我添加了几个样本)
IF OBJECT_ID('tempdb..#Employee') IS NOT NULL DROP TABLE #Employee
CREATE TABLE #Employee (Line1 VARCHAR(30), Line2 VARCHAR(30), Line3 VARCHAR(30),
City VARCHAR(17), State VARCHAR(2), ZIP VARCHAR(10))
GO
INSERT #Employee VALUES ('', '123 Somewhere', '', 'Detroit', 'MI', '48001')
INSERT #Employee VALUES ('123 Somewhere', 'Suite 500', '', 'Detroit', 'MI', '48002')
INSERT #Employee VALUES ('123 Somewhere', 'Suite 500', 'attn: JP', 'Detroit', 'MI', '48003')
SELECT * FROM #Employee
从这里开始,你所要做的就是将琴弦拼接在一起。这个版本假定你有空值和空字符串来分解。
SELECT
isnull(nullif(Line1, '') + char(13) + char(10), '')
+ isnull(nullif(Line2, '') + char(13) + char(10), '')
+ isnull(nullif(Line3, '') + char(13) + char(10), '')
+ City + ' ' + State + ' ' + ZIP
+ char(13) + char(10) + '------------------------------'
from #Employee
将其包装成函数:
CREATE FUNCTION dbo.SqueezeAddress
(
@Line1 varchar(30)
,@Line2 varchar(30)
,@Line3 varchar(30)
,@City varchar(17)
,@State varchar(2)
,@Zip varchar(10)
)
RETURNS varchar(200)
AS
BEGIN
RETURN isnull(nullif(@Line1, '') + char(13) + char(10), '')
+ isnull(nullif(@Line2, '') + char(13) + char(10), '')
+ isnull(nullif(@Line3, '') + char(13) + char(10), '')
+ @City + ' ' + @State + ' ' + @ZIP
+ char(13) + char(10) + '------------------------------'
END
GO
最后,将该函数放入查询中:
SELECT dbo.SqueezeAddress(Line1, Line2, Line3, City, State, Zip)
from #Employee
答案 1 :(得分:1)
假设空值实际上是NULL而不是空字符串,并且需要City,State和Zip:
;With AddressValues As
(
Select PK, Line1 As LineValue, 1 As LinePos
From AddressTable
Union All
Select PK, Line2, 2
From AddressTable
Union All
Select PK, Line3, 3
From AddressTable
Union All
Select PK, [City] + ', ' + [State] + ' ' + [Zip], 4
From AddressTable
)
, OrderedValues As
(
Select PK, LineValue
, Row_Number() Over( Partition By PK Order By LinePos ) As Num
From AddressValues
Where LineValue Is Not Null
)
, ValuesAsColumns As
(
Select PK
, Case When Num = 1 Then LineValue End As Line1
, Case When Num = 2 Then LineValue End As Line2
, Case When Num = 3 Then LineValue End As Line3
, Case When Num = 4 Then LineValue End As Line4
From OrderedValues
Group By PK
)
Update #tmpBilling
Set Line1 = VC.Line1
, Line2 = VC.Line2
, Line3 = VC.Line3
, Line4 = VC.Line4
From #tmpBilling As B
Join ValuesAsColumns As VC
On VC.PK = B.PK
修改强>
以下是函数形式的相同结果:
CREATE FUNCTION dbo.SqueezeAddress
(
@Line1 varchar(50)
, @Line2 varchar(50)
, @Line3 varchar(50)
, @City varchar(50)
, @State varchar(50)
, @Zip varchar(50)
, @LineNumToReturn int
)
RETURNS varchar(50)
AS
BEGIN
Declare @Result varchar(50);
With AddressValues As
(
Select @Line1 As LineValue, 1 As LinePos
Union All
Select @Line2, 2
Union All
Select @Line3, 3
Union All
Select @City + ', ' + @State + ' ' + @Zip, 4
)
, OrderedValues As
(
Select LineValue
, Row_Number() Over( Order By LinePos ) As Num
From AddressValues
Where LineValue Is Not Null
)
Select @Result = LineValue
From OrderedValues
Where Num = @LineNumToReturn
Return @Result
END
GO
Select dbo.SqueezeAddress(null, '123 Main St', null, 'Detroit', 'MI', '12345', 1)
, dbo.SqueezeAddress(null, '123 Main St', null, 'Detroit', 'MI', '12345', 2)
, dbo.SqueezeAddress(null, '123 Main St', null, 'Detroit', 'MI', '12345', 3)
, dbo.SqueezeAddress(null, '123 Main St', null, 'Detroit', 'MI', '12345', 4)
)
答案 2 :(得分:1)
更直接(也更容易调试,恕我直言):
-------------------------------------------------------------
-- assumptions:
--
-- * nullable fields never contain an nil (empty) string.
-- every nullable column will contain either a proper value
-- or NULL.
--
-- * zipcode is a 5- or 9-digit USPS zip code, without a dash.
-- Addresses lacking a zipcode will be NULL.
--------------------------------------------------------------
drop table dbo.address
go
create table dbo.address
(
id int not null identity(1,1) primary key clustered ,
line1 varchar(100) null ,
line2 varchar(100) null ,
line3 varchar(100) null ,
city varchar(100) null ,
state varchar(2) null ,
zipcode varchar(9) null ,
)
go
-----------------------------------------------------------------------
-- create a work table and rotate the source table such that
-- the work table contains 1 row for each non-null row for each address
-----------------------------------------------------------------------
drop table #addr
go
create table #addr
(
id int not null , -- pk.1
line_no int not null , -- pk.2
value varchar(100) not null ,
primary key clustered ( id , line_no ) ,
)
go
insert #addr ( id , line_no , value )
select addr.id , addr.line_no , addr.value
from ( select id = t.id ,
line_no = row_number() over ( partition by t.id order by t.seq ) ,
value = t.value
from ( select id = id ,
seq = 1 ,
value = line1
from dbo.address where line1 is not null
UNION
select id = id ,
seq = 2 ,
value = line2
from dbo.address where line2 is not null
UNION
select id = id ,
seq = 3 ,
value = line3
from dbo.address where line3 is not null
UNION
select id = id ,
seq = 4 ,
value = ltrim(rtrim(
coalesce( city , '' )
+ case when city is not null and state is not null then ', ' else '' end
+ coalesce( state , '' )
+ case when ( city is not null or state is not null ) and zipcode is not null then ' ' else '' end
+ coalesce( left(zipcode,5) , '' )
+ case when len(zipcode) = 9 then '-' + right(zipcode,4) else '' end
))
from dbo.address
where city is not null
OR state is not null
OR zipcode is not null
) t
) addr
---------------------------------------------------------------------
-- finally, do another table rotation to build the desired result set
---------------------------------------------------------------------
select id = addr.id ,
line1 = line1.value ,
line2 = line2.value ,
line3 = line3.value ,
line4 = line4.value
from #addr addr
left join #addr line1 on line1.id = addr.id and line1.line_no = 1
left join #addr line2 on line2.id = addr.id and line2.line_no = 2
left join #addr line3 on line3.id = addr.id and line3.line_no = 3
left join #addr line4 on line4.id = addr.id and line4.line_no = 4
order by addr.id