I am using SQL Server 2012. I will like to get final result from #sql into a temp table.Here is my code so far. Thanks for your help.
IF OBJECT_ID ('tempdb.dbo.#MY_DT_CTE') IS NOT NULL DROP TABLE #MY_DT_CTE
CREATE TABLE #MY_DT_CTE
([ROWID] INT NOT NULL IDENTITY (1,1)
,[YYYYMM] INT
)
; WITH MY_DT_CTE AS
(
SELECT CONVERT(INT,CONVERT(VARCHAR(6),EOMONTH(GETDATE(),-1),112)) AS [YYYYMM]
UNION
SELECT CONVERT(INT,CONVERT(VARCHAR(6),EOMONTH(GETDATE(),-2),112)) AS [YYYYMM]
UNION
SELECT CONVERT(INT,CONVERT(VARCHAR(6),EOMONTH(GETDATE(),-3),112)) AS [YYYYMM]
UNION
SELECT CONVERT(INT,CONVERT(VARCHAR(6),EOMONTH(GETDATE(),-4),112)) AS [YYYYMM]
UNION
SELECT CONVERT(INT,CONVERT(VARCHAR(6),EOMONTH(GETDATE(),-5),112)) AS [YYYYMM]
UNION
SELECT CONVERT(INT,CONVERT(VARCHAR(6),EOMONTH(GETDATE(),-6),112)) AS [YYYYMM]
)
INSERT INTO #MY_DT_CTE
SELECT [YYYYMM] FROM MY_DT_CTE
ORDER BY [YYYYMM] DESC;
-- SELECT * FROM #MY_DT_CTE
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(YYYYMM)
FROM (SELECT p.YYYYMM FROM #MY_DT_CTE AS p
GROUP BY p.YYYYMM) AS x;
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.YYYYMM FROM #MY_DT_CTE AS p
) AS j
PIVOT
(
COUNT(YYYYMM) FOR YYYYMM IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1,
'')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
Need to bring this result #sql into a temp table.
201605 201606 201607 201608 201609 201610
An easy way would be to use a global temporary table. This can be selected into in the dynamic SQL scope to automatically have the desired schema and still be available after that exits.
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
INTO ##GlobalTemp
FROM
(
SELECT p.YYYYMM FROM #MY_DT_CTE AS p
) AS j
PIVOT
(
COUNT(YYYYMM) FOR YYYYMM IN (' + STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '') + ')
) AS p;';
EXEC sp_executesql #sql;
SELECT *
FROM ##GlobalTemp
However this can cause issues with naming clashes if the code is ever executed concurrently.
It is possible to use a local temp table but the code is more involved as it involves creating a temp table at the upper scope and then using dynamic SQL to alter it to the dynamically determined schema before inserting into it.
CREATE TABLE #T
(
Dummy INT
);
SET #sql = 'ALTER TABLE #T ADD Dummy2 INT' + REPLACE(REPLACE(#columns, 'p.', ''), ']', '] int') + ';
ALTER TABLE #T DROP COLUMN Dummy, Dummy2;'
EXEC (#sql);
SET #sql = N'
INSERT INTO #T
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.YYYYMM FROM #MY_DT_CTE AS p
) AS j
PIVOT
(
COUNT(YYYYMM) FOR YYYYMM IN (' + STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '') + ')
) AS p;';
EXEC sp_executesql #sql;
SELECT *
FROM #T
Related
I'm trying to Pivot a Table on X and Y position. The table is in a format similar to below.
Each row has a value which is relative to its Row and Column Position.'AThing' and 'FileName' are to be ignored in the data set.
So if this was pivoted we would get:
Iv'e been trying for a while but can't seem to figure it out, any ideas?
EDIT: Number of Fields are dynamic per 'FileName'. I have managed to extract the column names but not the data using:
-- Construct List of Columns to Pivot
SELECT #PivotCols =
STUFF(
(SELECT ',' + QUOTENAME(FieldName)
FROM #Data
GROUP BY ColPos, FieldName
ORDER BY ColPos ASC
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #PivotQuery =
SELECT ' + #PivotCols + N'
FROM
(
SELECT ColPos, FieldName
FROM #Data
GROUP BY ColPos, FieldName
) x
PIVOT
(
MIN(ColPos)
FOR FieldName IN (' + #PivotCols + N')
) p'
EXEC sp_executesql #PivotQuery
Please try this code:
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(FieldName)
FROM (SELECT distinct p.FieldName FROM Tablename AS p
) AS x;
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.Value, p.FieldName, p.RowPos
FROM Tablename AS p
) AS j
PIVOT
(
MAX(Value) FOR FieldName IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
I just wrote a script here but I have no idea how to save it as a view or a table. It is dynamically creating columns from rows
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME([Period])
FROM (SELECT p.Period FROM dbo.[refv_IRR3_Op_Rev] AS p
INNER JOIN [dbo].[refv_IRR3_Op_Rev] AS o
ON p.RMDF = o.RMDF
GROUP BY P.Period) AS x;
SET #sql = N'
SELECT [Region]
,[LAU]
,[RMDF]
, ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT [Region]
,[LAU]
,[RMDF]
,[Period]
,[Net_Operating_Cashflow]
FROM [FTTx_Build].[dbo].[refv_IRR3_Op_Rev]
) AS j
PIVOT
(
SUM([Net_Operating_Cashflow]) FOR Period IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
How do I save it as a view or table?
short answer: you can't. However you can build a stored procedure from your code and call that when you need those results.
I have a dynamic pivoted query which generates a result set and I want to insert that data into a table. But the problem is columns are dropped or generated by the time. So by the time I cannot predict columns. That is why I created a dynamic pivoted dataset. So how to insert that data set into table?
One solution is to drop and recreate the table every time but I don't know how to do it. I tried CTE, TEMP table but EXEC support only select, insert, update, delete statement:
DECLARE #columns NVARCHAR(MAX), #sqlquery NVARCHAR(MAX), #orderby Nvarchar(MAX),#value Nvarchar(max);
SET #columns = N'';
SET #value=N'0'
SELECT #columns += N', ' + QUOTENAME([Note_Type])
FROM
(
SELECT distinct
No_T
FROM [DS_DM].[dbo].[DAILY_TABLE]
where No_T not in (570,80,150,590,80,99)
)as A order by No_T
SET #sqlquery = N'
Select
K._Number
,D.C_Number
,' + STUFF(#columns, 1, 2, '') + '
from
(
select
_Number
,' + STUFF(#columns, 1, 2, '') + '
from
(
select distinct
right(REPLICATE('+#value+',11) +_Number,11) as [_Number]
,No_t
,No_T_Des
FROM [DS_DM].[dbo].[DAILY_TABLE]
where No_T not in (570,80,150,590,80,99)
)AS J
pivot
(
count(No_T_Des) FOR [No_t] IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
)P
)K
left join
[DS_DM].[dbo].[D_TABLE] D on k._Number = D._Number
';
EXEC sp_executesql #sqlquery
I've modified your code to reflect my proposed solution.
IF OBJECT_ID (N'NEW_TABLE', N'U') IS NOT NULL
BEGIN
DROP TABLE NEW_TABLE
END
DECLARE #columns NVARCHAR(MAX), #sqlquery NVARCHAR(MAX), #orderby Nvarchar(MAX),#value Nvarchar(max);
SET #columns = N'';
SET #value=N'0'
SELECT #columns += N', ' + QUOTENAME([Note_Type])
FROM
(
SELECT distinct
No_T
FROM [DS_DM].[dbo].[DAILY_TABLE]
where No_T not in (570,80,150,590,80,99)
)as A order by No_T
SET #sqlquery = N'
Select
K._Number
,D.C_Number
,' + STUFF(#columns, 1, 2, '') + '
INTO NEW_TABLE
from
(
select
_Number
,' + STUFF(#columns, 1, 2, '') + '
from
(
select distinct
right(REPLICATE('+#value+',11) +_Number,11) as [_Number]
,No_t
,No_T_Des
FROM [DS_DM].[dbo].[DAILY_TABLE]
where No_T not in (570,80,150,590,80,99)
)AS J
pivot
(
count(No_T_Des) FOR [No_t] IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
)P
)K
left join
[DS_DM].[dbo].[D_TABLE] D on k._Number = D._Number
';
EXEC sp_executesql #sqlquery
So I found the answers to my questions.
there are 2 fileds which remais static every time. so I've created ETL that drop that table and recreate every single day with those two fileds. and rest of the 66 columns which are dynamic (drops or newly created) every day. so i've made a cursor for that which loop through all of that categories and altering that table that've created and added that code to ETL
So bassically Every single day that ETL Runs Drop the existing table, Create new table with the 2 static filds and altering same table using cursor with the dynamic filds.
while answering one question i got struck with other question in mind.when it is normal pivot it is working fine but if i'm trying to do Dynamic query when the problem arises
after answering he asked for Dynamic Pivot
PIVOT the date column in SQL Server 2012
if OBJECT_ID('tempdb..#temp') is not null
begin
drop table #temp
end
CREATE table #temp (dated varchar(10),E1 int,E2 int,E3 int,E4 int)
insert into #temp
(dated,E1,E2,E3,E4)values
('05-27-15',1,1,2,3),
('05-28-15',2,3,NULL,5),
('05-29-15',3,4,null,2)
DECLARE #statement NVARCHAR(max)
,#columns NVARCHAR(max)
SELECT #columns = ISNULL(#columns + ', ', '') + N'[' + tbl.dated + ']'
FROM (
SELECT DISTINCT dated
FROM #temp
) AS tbl
SELECT #statement = 'Select P.col,MAX('+#columns+') from (
select col,' + #columns + ' from (
select * from #temp
CROSS APPLY(values(''E1'',E1),(''E2'',E2),(''E3'',E3),(''E4'',E4))cs (col,val))PP
PIVOT(MAX(val) for dated IN (' + #columns + ')) as PVT)P
GROUP BY P.COL
'
PRINT #statement
EXEC sp_executesql #statement = #statement
my problem is how can i take MAX() conditions for the all dates dynamically like
max(05-27-15),max(05-28-15) etc dates are coming dynamically how to assign max condition
Moving the MAX aggregate to column list variable will fix the issue
DECLARE #statement NVARCHAR(max),
#columns NVARCHAR(max),
#select_columns NVARCHAR(max)
SELECT #select_columns = Isnull(#select_columns + ', ', '')+ N'MAX([' + tbl.dated + '])'
FROM (SELECT DISTINCT dated
FROM #temp) AS tbl
SELECT #columns = Isnull(#columns + ', ', '') + N'[' + tbl.dated+ ']'
FROM (SELECT DISTINCT dated
FROM #temp) AS tbl
SELECT #statement = 'Select P.col,' + #select_columns
+ ' from (
select col,' + #columns
+ ' from (
select * from #temp
CROSS APPLY(values(''E1'',E1),(''E2'',E2),(''E3'',E3),(''E4'',E4))cs (col,val))PP
PIVOT(MAX(val) for dated IN (' + #columns
+ ')) as PVT)P
GROUP BY P.COL
'
PRINT #statement
EXEC sp_executesql #statement = #statement
Let's jump straight into it. Here's the code
SELECT [prov], [201304], [201305], [201306], [201307]
FROM (
SELECT [prov], [arrival], [Amount]
FROM [tblSource]) up
PIVOT (SUM([Amount]) FOR [arrival] IN ([201304], [201305], [201306], [201307])) AS pvt
GO
It brings me back an ever so lovely table. I was wondering how I would get the totals for each "date" column to show in an appended last row?
In addition, the underlying table will have more data added, specifically more dates. This means that 201308 will be added next, then 201309 etc
This will mean that currently I will have to amend the code above each month to reflect the addition. Is there anyway around this?
You can dynamically create the columns using dynamic SQL, however, I would really recommend handling dynamic pivots in a layer designed for it, such as SSRS or excel.
DECLARE #SQL NVARCHAR(MAX) = '',
#SQL2 NVARCHAR(MAX) = '',
#SQL3 NVARCHAR(MAX) = '';
-- COMPILE THE UNIQUE VALUES FOR ARRIVAL THAT NEED TO BE PIVOTED
SELECT #SQL = #SQL + ',' + QUOTENAME(Arrival),
#SQL2 = #SQL2 + '+ISNULL(' + QUOTENAME(Arrival) + ', 0)',
#SQL3 = #SQL3 + ',' + QUOTENAME(Arrival) + ' = ISNULL(' + QUOTENAME(Arrival) + ', 0)'
FROM (SELECT DISTINCT Arrival FROM tblSource) s;
-- COMBINE THEM INTO A SINGLE QUERY
SET #SQL = 'SELECT [Prov]' + #SQL3 + ', [Total] = ' + STUFF(#SQL2, 1, 1, '') + '
FROM ( SELECT Arrival, Prov, Amount
FROM [tblSource]
UNION ALL
SELECT Arrival, ''Total'', SUM(Amount)
FROM [tblSource]
GROUP BY Arrival
) up
PIVOT
( SUM(Amount)
FOR Arrival IN (' + STUFF(#SQL, 1, 1, '') + ')
) pvt;';
-- EXECUTE THE QUERY
EXECUTE SP_EXECUTESQL #SQL;
This creates and executes the following SQL:
SELECT [Prov],
[2013-01-01] = ISNULL([2013-01-01], 0),
[2013-02-01] = ISNULL([2013-02-01], 0),
[Total] = ISNULL([2013-01-01], 0) + ISNULL([2013-02-01], 0)
FROM ( SELECT Arrival, Prov, Amount
FROM [tblSource]
UNION ALL
SELECT Arrival, 'Total', SUM(Amount)
FROM [tblSource]
GROUP BY Arrival
) up
PIVOT
( SUM(Amount)
FOR Arrival IN ([2013-01-01],[2013-02-01])
) pvt;
It is the query below union in the subquery up that adds the total row at the bottom, and the row total is simply created by adding all the columns in the row.
Example on SQL Fiddle
I will stress again though, I really recommend handling manipulation of data like this outside of SQL.
EDIT
An alternative to using the UNION to get the the total row is to use GROUPING SETS as follows:
DECLARE #SQL NVARCHAR(MAX) = '',
#SQL2 NVARCHAR(MAX) = '',
#SQL3 NVARCHAR(MAX) = '';
-- COMPILE THE UNIQUE VALUES FOR ARRIVAL THAT NEED TO BE PIVOTED
SELECT #SQL = #SQL + ',' + QUOTENAME(Arrival),
#SQL2 = #SQL2 + '+ISNULL(' + QUOTENAME(Arrival) + ', 0)',
#SQL3 = #SQL3 + ',' + QUOTENAME(Arrival) + ' = ISNULL(' + QUOTENAME(Arrival) + ', 0)'
FROM (SELECT DISTINCT Arrival FROM tblSource) s;
-- COMBINE THEM INTO A SINGLE QUERY
SET #SQL = 'SELECT [Prov]' + #SQL3 + ', [Total] = ' + STUFF(#SQL2, 1, 1, '') + '
FROM ( SELECT Arrival, Prov = ISNULL(Prov, 'Total'), Amount = SUM(Amount)
FROM [tblSource]
GROUP BY GROUPING SETS((Prov, arrival), (arrival))
) up
PIVOT
( SUM(Amount)
FOR Arrival IN (' + STUFF(#SQL, 1, 1, '') + ')
) pvt;';
-- EXECUTE THE QUERY
EXECUTE SP_EXECUTESQL #SQL;
SAMPLE TABLE
CREATE TABLE #TEMP([prov] VARCHAR(100),[arrival] INT, AMOUNT NUMERIC(12,2))
INSERT INTO #TEMP
SELECT 'A' [prov],'201304' [arrival],100 AMOUNT
UNION ALL
SELECT 'A' ,'201305' ,124
UNION ALL
SELECT 'A' ,'201306' ,156
UNION ALL
SELECT 'B' ,'201304' ,67
UNION ALL
SELECT 'B' ,'201305' ,211
UNION ALL
SELECT 'B' ,'201306' ,176
UNION ALL
SELECT 'C' ,'201304' ,43
UNION ALL
SELECT 'C' ,'201305' ,56
UNION ALL
SELECT 'C' ,'201306' ,158
QUERY
You can use ROLLUP to get the row total. More about ROLLUP here
-- Get the columns for dynamic pivot
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + CAST([arrival] AS VARCHAR(50)) + ']',
'[' + CAST([arrival] AS VARCHAR(50)) + ']')
FROM (SELECT DISTINCT [arrival] FROM #TEMP) PV
ORDER BY [arrival]
-- Replace NULL value with zero
DECLARE #NulltoZeroCols NVARCHAR (MAX)
SELECT #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+[arrival]+'],0) AS ['+[arrival]+']'
FROM (SELECT DISTINCT CAST([arrival] AS VARCHAR(50)) [arrival] FROM #TEMP)TAB
ORDER BY CAST([arrival]AS INT) FOR XML PATH('')),2,8000)
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT [prov],' + #NullToZeroCols + ' FROM
(
SELECT
ISNULL([prov],''Total'')[prov],
SUM(AMOUNT)AMOUNT ,
ISNULL(CAST([arrival] AS VARCHAR(50)),''Total'')[arrival]
FROM #TEMP
GROUP BY [arrival],[prov]
WITH ROLLUP
) x
PIVOT
(
MIN(AMOUNT)
FOR [arrival] IN (' + #cols + ')
) p
ORDER BY CASE WHEN ([prov]=''Total'') THEN 1 ELSE 0 END,[prov]'
EXEC SP_EXECUTESQL #query
Note : If you do not want to replace NULL with zero, just replace #NullToZeroCols with #cols in outer query of dynamic pivot