I have a table like this
Id Name FromAddress ToAddress
1 Joey ABC JKL
2 Joey DEF MNP
3 Joey GHI OQR
ok, I created a temp table to do some testing on. The solution requires an unpivot first. I recommend running with/without the extra test data to get a sense of some other behaviors that surround this solution -- the weirdness that comes with the MAX aggregation and lack of new rows that you might have expected when changing the value in 'name'.
GL. Hope it helps.
-------------------------
-- Some test data here
CREATE table #addresses ( Id int, Name varchar(5), FromAddress varchar(5), ToAddress varchar(5))
insert into #addresses(id, Name, FromAddress, ToAddress) Values
(1,'Joey', 'ABC', 'JKL')
, (2,'Joey', 'DEF', 'MNO')
, (3,'Joey', 'GHI', 'PQR')
, (4,'Spike', 'XXX', 'YYY')
, (1,'Spike', 'QQQ', 'RRR')
-------------------------
-- Solution starts here. create a temp table and unpivot your data into it.
-- Your initial technique of does not work, PIVOT only supports one aggregation
CREATE table #unpvt(RowColCode varchar(20), vals varchar(20))
Insert into #unpvt
SELECT ColCode + '_' + Cast(ID as varchar(2)) as RowColCode, vals
FROM #addresses a
UNPIVOT
(vals for ColCode in (Name,FromAddress,ToAddress)) c
-------------------------
-- Read the temp table for a column list
declare @ColList nvarchar(max)
set @ColList = STUFF((
SELECT distinct ',[' + t.RowColCode + ']'
FROM #unpvt t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
-------------------------
-- 're pivot' the data using your new column list
declare @qry varchar(max)
set @qry = '
select *
from
#unpvt
PIVOT(
MAX(vals)
FOR RowColCode in (' +@ColList + ')
) rslt
'
execute(@qry)
I believe the problem is the IN ()
expression in the PIVOT
s. The column list explicitly has to be a list of fields names, not a function and not a list of varchar literals or function values. You've got a REPLACE()
function in there. The engine expects to be looking for a field named [REPLACE]
and then gets confused by the open parentheses that shows up.
This is valid (square brackets for emphasis):
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
([Emp1], [Emp2], [Emp3], [Emp4], [Emp5])
)AS unpvt;
This is not:
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
('Emp1', 'Emp2', 'Emp3', 'Emp4', 'Emp5')
)AS unpvt;
And this is not valid:
SELECT VendorID, Employee, Orders
FROM
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt) p
UNPIVOT
(Orders FOR Employee IN
(REPLACE('Emp1','1','A'), REPLACE('Emp2','2','B'))
)AS unpvt;
Replace the execute(@query)
with a select @query
or print @query
to see the query your code generated and troubleshoot the syntax in a query analyzer that way. Then work backwards.
You want to do the REPLACE()
at the same level you're building the query. The query that ends up in the @query
variable should already have the column names fixed.
Alternately, you could generate @colsFromLabels
, @colsToLabels
, @colsFrom
and @colsTo
with the former two have the 'from'
and to
bits added and the latter two just being column names.
Your desired output is a little gross as far as square bracket escaping, too.