My original table is this;
TableName= NewRetail
CustomerID 1 2 3 4 5 6 7.....30
1 30 31 Null Null Null Null Null
2 24 78 35 72 Null Null Null
I want to store this table in 'Retail'
CustomerId Itemset
1 30
1 31
2 24
2 78
2 35
2 72
There are no duplicates in any row in Original(Source) Table.
Thanks. I tried using Loops but couldn't make it work. Been stuck at it since three days.
You can use table valued constructor with Cross apply to unpivot the data
SELECT CustomerID,
Itemset
FROM Yourtable
CROSS apply (VALUES ([1]),([2]),([3]),([4]),([5]),([6]),([7]),...) cs (Itemset)
WHERE Itemset IS NOT NULL
Dynamic Version
DECLARE #itemset VARCHAR(max)='',
#sql NVARCHAR(max);
WITH cte
AS (SELECT TOP 30 Row_number()OVER(ORDER BY (SELECT NULL)) RN
FROM sys.columns)
SELECT #itemset += '(' + Quotename(RN) + '),'
FROM cte
SET #itemset = LEFT(#itemset, Len(#itemset) - 1)
SET #sql = 'SELECT CustomerID,
Itemset
FROM Yourtable
CROSS apply (VALUES ' + #itemset
+ ') cs (Itemset)
WHERE Itemset IS NOT NULL '
EXEC Sp_executesql #sql
You can do this using UNION ALL:
SELECT *
FROM (
SELECT CustomerId, [1] AS ItemSet FROM NewRetail UNION ALL
SELECT CustomerId, [2] FROM NewRetail UNION ALL
SELECT CustomerId, [3] FROM NewRetail UNION ALL
SELECT CustomerId, [4] FROM NewRetail UNION ALL
SELECT CustomerId, [5] FROM NewRetail UNION ALL
SELECT CustomerId, [6] FROM NewRetail UNION ALL
SELECT CustomerId, [7] FROM NewRetail UNION ALL
...
SELECT CustomerId, [30] FROM NewRetail
)t
WHERE ItemSet IS NOT NULL
ORDER BY CustomerId
Using dynamic SQL:
;WITH Tally(N) AS(
SELECT TOP 30 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM sys.columns
)
SELECT #sql = #sql +
CASE
WHEN #sql = '' THEN 'SELECT CustomerId, [' + CONVERT(VARCHAR(2), N) + '] AS ItemSet FROM NewRetail'
ELSE ' UNION ALL' + CHAR(10) +' SELECT CustomerId, [' + CONVERT(VARCHAR(2), N) + '] FROM NewRetail'
END
FROM Tally
SELECT #sql =
'SELECT *
FROM (
' + #sql + CHAR(10) +
')t
WHERE ItemSet IS NOT NULL
ORDER BY CustomerId'
PRINT #sql
EXEC (#sql)
It is a simple UNPIVOT operation. NULLs automatically eliminated from result:
declare #t table(custid int, [1] int, [2] int, [3] int)
insert into #t values
(1, 10, 30, null),
(2, 30, 40, 50)
select custid, c from #t
unpivot(c for p in([1], [2], [3])) p
Fiddle http://sqlfiddle.com/#!6/9eecb/1733
Related
I have a table that has many InsuranceNo's for unique MemberIDs. If there are more than one InsuranceNo, I want the InsuranceNo's to shift to a column, so in the end there is one line per MemberID, with all the iterations of that ID's InsuranceNo's as a Column.
MemberID InsuranceNo
--------------------------
123456 dser
124571 jklh
123456 abcd
I want it to look like this:
MemberID InsuranceNo1 InsuranceNo2
-----------------------------------------------------
123456 dser abcd
124571 jklh
Thank you!
Yet another option... Just change "YourTable" to your actual table name.
Example
Declare #SQL varchar(max) = '
Select *
From (
Select MemberID
,Item = concat(''InsuranceNo'',row_number() over (Partition By MemberID Order By (Select NULL)))
,Value = InsuranceNo
From YourTable
) A
Pivot (max([Value]) For [Item] in (' + Stuff((Select ','+QuoteName(concat('InsuranceNo',ColNr))
From (Select Distinct ColNr=row_number() over (Partition By MemberID Order By (Select NULL)) from YourTable ) A
For XML Path('')),1,1,'') + ') ) p'
--Print #SQL
Exec(#SQL);
Returns
MemberID InsuranceNo1 InsuranceNo2
123456 dser abcd
124571 jklh NULL
If it helps wrap your head around PIVOT, the SQL Generated looks like this:
Select *
From (
Select MemberID
,Item = concat('InsuranceNo',row_number() over (Partition By MemberID Order By (Select NULL)))
,Value = InsuranceNo
From YourTable
) A
Pivot (max([Value]) For [Item] in ([InsuranceNo1],[InsuranceNo2]) ) p
I prefer a dynamic cross tab to the dynamic pivot. I find the syntax far less obtuse and it is super easy if you need to add additional columns. Here is I would go about tackling this. Of course in your case you don't need a temp table because you have an actual table to use.
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
MemberID int
, InsuranceNo varchar(10)
)
insert #Something values
(123456, 'dser')
, (124571, 'jklh')
, (123456, 'abcd')
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by MemberID order by InsuranceNo) as RowNum
from #Something
)
select MemberID';
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by MemberID order by MemberID';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then InsuranceNo end) as InsuranceNo' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by MemberID
order by COUNT(*) desc
)
select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute
I am trying to create pivot where row is Brand and SKU, sum is qty for column YYMM, but I'm not sure why it is throwing an error. Please help.
Code:
DECLARE #TABLE TABLE
(
SKU VARCHAR(10),
YYMM VARCHAR(50),
BRAND VARCHAR(50),
QTY INT
)
INSERT INTO #TABLE
SELECT '104591168', '2015-January', 'abott', 2 UNION ALL
SELECT '104580709', '2016-January', 'GSK', 2 UNION ALL
SELECT '104720038', '2017-January', 'RANBAXCY', 2 UNION ALL
SELECT '10467011A', '2018-January', 'abott', 2 UNION ALL
SELECT '104590691', '2019-January', 'abott', 10
Pivot code:
select *
from
(select
BRAND, sku, QTY, YYMM
from #TABLE) src
pivot
(sum(QTY)
for [Year Month]
You forgot to finish your query.
Please see the bottom of MSDN article for PIVOT examples.
I would guess that you wanted your query to look something like this:
SELECT *
FROM(
SELECT BRAND, sku, QTY, YYMM
FROM #TABLE
) AS src
PIVOT(
sum(QTY)
for [YYMM] IN( [2015-January], [2016-January], [2017-January] /* add other moneths here */ )
) AS Pivoted
We can make it as Dynamic sql
DECLARE #Column NVARCHAR(max),
#Column2 NVARCHAR(max),
#Sql NVARCHAR(max)
SELECT #Column = Stuff((SELECT DISTINCT ', '
+ Quotename(Cast(yymm AS VARCHAR(20)))
FROM #table
FOR xml path ('')), 1, 1, '')
SELECT #Column2 = Stuff((SELECT DISTINCT ', ' + 'ISNULL('
+ Quotename(Cast(yymm AS VARCHAR(20)))
+ ','
+ '''0''' + ') AS '
+ Quotename(Cast(yymm AS VARCHAR(20)))
FROM #table
FOR xml path ('')), 1, 1, '')
SET #Sql='
SELECT BRAND ,sku,'+#Column2+'
FROM(
SELECT *
FROM #TABLE
) AS src
PIVOT(
sum(QTY)
for [YYMM] IN('+#Column+')
) AS Pivoted
'
PRINT #Sql
EXEC(#Sql)
Result
BRAND sku 2015-January 2016-January 2017-January 2018-January 2019-January
--------------------------------------------------------------------------------------------------------
abott 104590691 0 0 0 0 10
abott 104591168 2 0 0 0 0
abott 10467011A 0 0 0 2 0
GSK 104580709 0 2 0 0 0
RANBAXCY 104720038 0 0 2 0 0
I am using sql server 2012 and I have a table like this:
FieldName FieldValue
DivisionId 1
DivisionId 2
DivisionId 3
CompanyId 2
CompanyId 3
LocationId 1
What i want is concatenate columns and form a where clause query like this
(DivisionId=1 OR DivisionId=2 OR DivisionId=3) AND
(CompanyId=2 OR CompanyId=3) AND
(LocationId = 1)
What I was able to figure out is, I need to concatenate columns values like this
DECLARE #Query VARCHAR(MAX)
SELECT #Query =
ISNULL(#Query,'') + IIF(#Query IS NOT NULL, ' AND ', '') + CONCAT(DF.FieldName,'=',DA.FieldValue)
FROM TABLE
SELECT #Query;
But this code will not handle OR condition.
Try following solution:
DECLARE #eav TABLE (
FieldName NVARCHAR(128) NOT NULL,
FieldValue VARCHAR(50) NOT NULL
)
INSERT #eav (FieldName, FieldValue)
SELECT 'DivisionId', 1 UNION ALL
SELECT 'DivisionId', 2 UNION ALL
SELECT 'DivisionId', 3 UNION ALL
SELECT 'CompanyId ', 2 UNION ALL
SELECT 'CompanyId ', 3 UNION ALL
SELECT 'LocationId', 1
DECLARE #Predicate NVARCHAR(MAX) = N''
SELECT #Predicate = #Predicate
+ CASE WHEN rn_asc = 1 THEN ' AND ' + FieldName + ' IN (' + LTRIM(FieldValue) ELSE '' END
+ CASE WHEN rn_asc > 1 THEN ', ' + LTRIM(FieldValue) ELSE '' END
+ CASE WHEN rn_desc = 1 THEN ') ' ELSE '' END
FROM (
SELECT *,
rn_asc = ROW_NUMBER() OVER(PARTITION BY x.FieldName ORDER BY x.FieldValue),
rn_desc= ROW_NUMBER() OVER(PARTITION BY x.FieldName ORDER BY x.FieldValue DESC)
FROM #eav x
) y
ORDER BY FieldName, FieldValue
SELECT #Predicate = STUFF(#Predicate, 1, 5, '')
SELECT #Predicate
-- Results: CompanyId IN (2, 3) AND DivisionId IN (1, 2, 3) AND LocationId IN (1)
Then you could use #Predicate to create a dynamic SQL SELECT statement (for example)
DECLARE #SqlStatement NVARCHAR(MAX)
SET #SqlStatement = 'SELECT ... FROM dbo.Table1 WHERE ' + #Predicate
EXEC sp_executesql #SqlStatement
I have complicated query which works pretty good (MS SQL 2012). But it makes a mistake when sum up same price items. It count them correctly but only takes price once instead of taking them as a count number. It only appears when same item has same price and from same country. Here is my query ;
CREATE TABLE #ITEMS(ID INT,NAME VARCHAR(30))
INSERT INTO #ITEMS
SELECT 1, 'laptop'
UNION ALL
SELECT 2, 'phone'
UNION ALL
SELECT 3, 'playstation'
UNION ALL
SELECT 4, 'MacBook'
CREATE TABLE #Country(ID INT,NAME VARCHAR(30))
INSERT INTO #Country
SELECT 1, 'England'
UNION ALL
SELECT 2, 'Sweden'
UNION ALL
SELECT 3, 'Russia'
UNION ALL
SELECT 4, 'Italy'
CREATE TABLE [#Pre-Request](Id INT, countryId INT, ItemId INT)
INSERT INTO [#Pre-Request]
SELECT 1,1,3
UNION ALL
SELECT 2,2,1
UNION ALL
SELECT 3,2,2
UNION ALL
SELECT 4,3,3
UNION ALL
SELECT 5,3,3
UNION ALL
SELECT 6,2,3
CREATE TABLE #Offers(Id INT, PRICE VARCHAR(50))
INSERT INTO #Offers
SELECT 18,'257$'
UNION ALL
SELECT 19,'151$'
UNION ALL
SELECT 20,'424$'
UNION ALL
SELECT 21,'433$'
UNION ALL
SELECT 22,'151$'
CREATE TABLE #Request(Id INT, preReqId INT, requestStatus INT,winOfferId INT)
INSERT INTO #Request
SELECT 44, 1, 3, 18
UNION ALL
SELECT 11, 2, 4, 21
UNION ALL
SELECT 53, 3, 4, 20
UNION ALL
SELECT 87, 4, 3, 22
UNION ALL
SELECT 43, 5, 3, 19
UNION ALL
SELECT 43, 6, 2, Null
;WITH CTE AS
(
SELECT DISTINCT I.NAME ITEMNAME,C.NAME COUNTRYNAME
,CAST(REPLACE(TAB.PRICE,'$','')AS INT)PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN I.NAME END) OVER(PARTITION BY C.NAME,I.NAME) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
UNION
-- Used to select Item name and country that are not in Pre-request table and other tables
SELECT I.NAME ,C.NAME ,NULL,0
FROM #Items I
CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
-- Find the sum for number of items
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
SUM(PRICE)PRICE
FROM CTE
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
,CTE3 AS
(
-- Find the sum of PRICE
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
,SUM(CNTITEM)CNTITEM
FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
FROM CTE
)TAB
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV
ORDER BY ITEMNAME
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT COUNTRYNAME,' + #cols + ' FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
FROM #NEWTABLE
) x
PIVOT
(
MIN(NEWCOL)
FOR ITEMNAME IN (' + #cols + ')
) p
ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME'
EXEC SP_EXECUTESQL #query
and here is result ;
As you can see there are 2 "playstation" from "Russia" it takes correct count (2x) but only take 1 price "151$" (normally it must be 302$). How can I fix this without making major changes from query? Thank you.
I think this does what you want. The problem is in your first CTE where you do the item count and get a distinct on the ItemName, CountryName, and Price.
Instead of getting a distinct, do a group by as shown below and SUM the price.
SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
GROUP BY
I.NAME
,C.NAME
EDIT:
Here are the results I get:
Here's all of your code starting from the CTEs:
;WITH CTE AS
(
SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
GROUP BY
I.NAME
,C.NAME
UNION
-- Used to select Item name and country that are not in Pre-request table and other tables
SELECT I.NAME ,C.NAME ,NULL,0
FROM #Items I
CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
-- Find the sum for number of items
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
SUM(PRICE)PRICE
FROM CTE
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
,CTE3 AS
(
-- Find the sum of PRICE
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
,SUM(CNTITEM)CNTITEM
FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
FROM CTE
)TAB
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV
ORDER BY ITEMNAME
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT COUNTRYNAME,' + #cols + ' FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
FROM #NEWTABLE
) x
PIVOT
(
MIN(NEWCOL)
FOR ITEMNAME IN (' + #cols + ')
) p
ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME'
EXEC SP_EXECUTESQL #query
I have a functioning pivot query for static column values which i want to convert for dynamic column values.
The query is :
with a as (
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as 'Month'
,dateadd(month,datediff(month,0,logged_datetime),0) as 'Year'
from requests
)
select * from (
select datepart(m,a.Month) as 'months',datepart(YEAR,a.Year) as 'years',a.request_id
from a ) ps
pivot (
count(request_id) for [years] in ([2008],[2009],[2010],[2011],[2012],[2013],[2014],[2015])
) as pvt
order by months
For the dynamic query written below I am getting errors like
Msg 207, Level 16, State 1, Line 5 Invalid column name '2010'. :
select distinct datepart(year,dateadd(month,datediff(month,0,logged_datetime),0)) as 'Yearz'
into #t
FROM requests
DECLARE #Dynamic AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(Yearz)
FROM (SELECT * from #t) AS Yea
SET #Dynamic =
N'
select * from (
select datepart(m,dateadd(month,datediff(month,0,logged_datetime),0)) as months,' + #ColumnName + ',request_id
from requests ) ps
pivot (
count(request_id) for [Years] in (' + #ColumnName + ')
) as pvt
order by months
'
EXEC sp_executesql #Dynamic
SAMPLE TABLE
SELECT * INTO #REQUESTS
FROM
(
SELECT 1 request_id, '2012-06-01' logged_datetime
UNION ALL
SELECT 2 request_id, '2012-05-01'
UNION ALL
SELECT 11 request_id, '2012-06-01'
UNION ALL
SELECT 12 request_id, '2012-05-01'
UNION ALL
SELECT 3 request_id, '2012-07-01'
UNION ALL
SELECT 4 request_id, '2013-09-01'
UNION ALL
SELECT 5 request_id, '2013-10-01'
UNION ALL
SELECT 6 request_id, '2014-01-01'
UNION ALL
SELECT 7 request_id, '2014-02-01'
UNION ALL
SELECT 8 request_id, '2014-03-01'
UNION ALL
SELECT 9 request_id, '2014-05-01'
UNION ALL
SELECT 10 request_id, '2015-11-01'
)TAB
QUERY
Get the column for years and order it in numeric order
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + CAST([YEAR] AS VARCHAR(4)) + ']', '[' + CAST([YEAR] AS VARCHAR(4)) + ']')
FROM (SELECT DISTINCT YEAR(dateadd(month,datediff(month,0,logged_datetime),0)) [YEAR] FROM #REQUESTS) PV
ORDER BY CAST([YEAR] AS INT)
Now pivot the query
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT * FROM
(
-- We will get the count for a year and number of request_id in that month here as CNT column
select DISTINCT datepart(m,a.Month) as ''months'',datepart(YEAR,a.Year) as ''years'',
COUNT(*) OVER(PARTITION BY datepart(YEAR,a.Year),datepart(m,a.Month)) CNT
from
(
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as ''Month''
,dateadd(month,datediff(month,0,logged_datetime),0) as ''Year''
from #requests
)a
) x
PIVOT
(
MIN(CNT)
FOR years IN (' + #cols + ')
) p
ORDER BY MONTHS;'
EXEC SP_EXECUTESQL #query
Click here to view the result
I think you need to wrap your dynamic column names using the QUOTENAME function:
See example here: