多行值为一行值。有没有更好的解决方案呢?

时间:2015-10-09 03:05:06

标签: sql sql-server tsql

我要做的是根据ID将多行数据合并为一行。

我遇到的问题是我需要根据条件组合旧数据和新数据。 条件是,如果没有行值,则地址保持不变,如果有值,则根据属性的任何内容更改数据。

我已尝试使用STUFF AND FOR XML PATH进行字符串连接并使用case语句,但我无法获得所需的结果。顺便说一句,我相当绿,所以我可能没有正确使用它。

我已提供以下链接,说明我是如何解决此问题的。 这是漫长的一天,我可能会过度思考它。我想与您的专业人士联系,了解您的想法和可能更好的选择?

http://sqlfiddle.com/#!6/df574d/4/0

数据样本

CREATE TABLE [dbo].[AddressUpdate]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[AddressUpdateID] [int] NOT NULL,
[Property] [varchar](50) NULL,
[OldValue] [varchar](max) NULL,
[NewValue] [varchar](max) NULL,
)

CREATE TABLE [dbo].[Address]
(
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[AddressUpdateID] [int] NOT NULL,
[Address] [nvarchar](256) NULL,
[City] [nvarchar](256) NULL,
[State] [nvarchar](256) NULL,
[Zip] [nvarchar](256) NULL,
[CountryCode] [nchar](3) NULL,
)

INSERT INTO Address
(
--Address.ID,
AddressUpdateID,
Address,
[City],
State,
Zip,
CountryCode
)
VALUES
( 1, '654 5th Ave', 'Los Angelas', 'LA', '65445', 'USA'),
( 2, '123 Broadway Ave', 'Orlando', 'FL', '56476', 'USA'),
( 3, '789 Sunset Lane', 'Oakley', 'Alberta', 'L6H 0P7', 'CAN'),
( 4, '987 Country Dr', 'Flint', 'MI', '89874', 'USA'),
( 5, '741 Fast Street', 'MONTREAL', 'Quebec', 'T8V 0N5', 'CAN')


INSERT INTO AddressUpdate
(
--ID
AddressUpdateID,
Property,
OldValue,
NewValue
)
VALUES
(1, 'Address', '654 5th Ave', '5321 Hollywood'),
(2, 'Address', '123 Broadway Ave', '654 West Village'),
(2, 'City', 'Orlando', 'New York City'),
(2, 'State', 'FL', 'New York'),
(2, 'Zip', '56476', '8642'),
(4, 'Address', '987 Country Dr', '987 Maple Rd'),
(4, 'City', 'Flint', 'Alberta'),
(4, 'State', 'MI', 'GRANDE PRAIRIE'),
(4, 'Zip', '89874', 'T8V 0N5'),
(4, 'CountryCode', 'USA', 'CAN')

我是如何解决它的。

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
BEGIN
DROP TABLE #temp
END

CREATE TABLE #temp
(
AddressUpdateID BIGINT,
Address     NVARCHAR(256),
City        NVARCHAR(256),
State       NVARCHAR(256),
Zip         NVARCHAR(256),
CountryCode NCHAR(3)
)


INSERT INTO #temp (AddressUpdateID)
SELECT      
        DISTINCT a.AddressUpdateID
FROM 
        Address a


--update address
UPDATE #temp 
SET #temp.Address = au.NewValue
FROM AddressUpdate au
WHERE au.addressupdateid = #temp.AddressUpdateID
AND au.property = 'Address'


--SELECT * FROM #temp
--update null address with current value
UPDATE #temp
SET #temp.Address = a.Address
FROM Address a 
WHERE #temp.Address IS NULL AND #temp.AddressUpdateID = a.AddressUpdateID

--update city
UPDATE #temp 
SET #temp.City = au.NewValue
FROM AddressUpdate au
WHERE au.addressupdateid = #temp.AddressUpdateID
AND au.property = 'City'

--update null city with current value
UPDATE #temp
SET #temp.City = a.City
FROM Address a  
WHERE #temp.City IS NULL AND #temp.AddressUpdateID = a.AddressUpdateID

--update state
UPDATE #temp 
SET #temp.State = au.NewValue
FROM AddressUpdate au
WHERE au.addressupdateid = #temp.AddressUpdateID
AND au.property = 'State'

--update null State with current value
UPDATE #temp
SET #temp.State = a.State
FROM Address a 
WHERE #temp.State IS NULL AND #temp.AddressUpdateID = a.AddressUpdateID

--update zip
UPDATE #temp 
SET #temp.Zip = au.NewValue
FROM AddressUpdate au
WHERE au.addressupdateid = #temp.AddressUpdateID 
AND au.property = 'Zip'

--update null zip with current value
UPDATE #temp
SET #temp.Zip = a.Zip
FROM Address a  
WHERE #temp.Zip IS NULL AND #temp.AddressUpdateID = a.AddressUpdateID

--update country code
UPDATE #temp 
SET #temp.CountryCode = au.NewValue
FROM AddressUpdate au
WHERE au.addressupdateid = #temp.AddressUpdateID
AND au.property = 'CountryCode'

--update null country code with current value
UPDATE #temp
SET #temp.CountryCode = a.CountryCode
FROM Address a 
WHERE #temp.CountryCode IS NULL AND #temp.AddressUpdateID = a.AddressUpdateID


SELECT  
        [Old Address] = a.Address + ' ' + a.City +', ' + a.State + ' ' + a.Zip + ' ' + a.CountryCode
        ,[New Address] = t.Address + ' ' + t.City +', ' + t.State + ' ' + t.Zip + ' ' + t.CountryCode

FROM    
    Address a
LEFT JOIN #temp t ON t.AddressUpdateID = a.AddressUpdateId

1 个答案:

答案 0 :(得分:0)

UNPIVOT首先Address表,JOIN表示AddressUpdate。之后,使用FOR XML PATH('')进行字符串连接:

SQL Fiddle

;WITH CteAddressUnpivot(Id, AddressUpdateId, Property, Val) AS(
    SELECT
        a.Id,
        a.AddressUpdateID,
        x.Property,
        x.Val
    FROM Address a
    CROSS APPLY( VALUES
        ('Address', Address),
        ('City', City),
        ('State', State),
        ('Zip', Zip),
        ('CountryCode', CountryCode)
    )x(Property, Val)
)
SELECT
    OldAddress  = a.Address + ' ' + a.City +', ' + a.State + ' ' + a.Zip + ' ' + a.CountryCode,
    NewAddress  = x.NewAddress 
FROM Address a
CROSS APPLY(
    SELECT STUFF((
        SELECT ' ' + ISNULL(au.NewValue, cau.Val)
        FROM CteAddressUnpivot cau
        LEFT JOIN AddressUpdate au
            ON au.Property = cau.Property
            AND au.AddressUpdateID = cau.AddressUpdateId
        WHERE
            cau.Id = a.ID
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
    , 1, 1, '')
)x(NewAddress)