Dynamic Pivot SQL in the Common Table Expression (CTE) - sql-server

I am trying to Pivot a result of a CTE. Due to the privacy laws i cannot put my query and resultset here but the example looks like the below:
WITH CTE1
AS ( select ....)
,CTE2
AS (Select...)
,CTE3
as (Select...)
Below is the result of my CTE2:
and i want the result as
The main issue i am having here is to pivot the resultset with multiple and dynamic Pivot columns between CTE2 and CTE3 as i need to use the Pivot data in CTE3. Is there any solution without changing the CTE's to TempTable? Any help will be appreciated.

I think it's going to be something like this.
Dynamic Pivot:
DECLARE #query VARCHAR(4000)
DECLARE #years VARCHAR(2000)
SELECT #years = STUFF(( SELECT DISTINCT'],[' + [factor_label]
FROM [TEMP_lacp_factors]
ORDER BY '],[' + [factor_label]
FOR XML PATH('')
), 1, 2, '') + ']'
SET #query =
'SELECT * FROM
(
SELECT [date_],[issue_id],[cusip],[Factor_value],[factor_label]
FROM [TEMP_lacp_factors]
)t
PIVOT (MAX([factor_value]) FOR [factor_label]
IN ('+#years+')) AS pvt'
EXECUTE (#query)
Dynamic Pivot and Select Into:
-- Drop the table; you create it dynamically
Drop Table tempTable
--Start creating all objects for Dyanmic Pivot
DECLARE #query VARCHAR(4000)
DECLARE #years VARCHAR(2000)
SELECT #years = STUFF(( SELECT DISTINCT'],[' + [factor_label]
FROM [TEMP_lacp_factors]
ORDER BY '],[' + [factor_label]
FOR XML PATH('')
), 1, 2, '') + ']'
SET #query =
-- Objects that are created above, are put into the table you are about to create below
'SELECT * INTO tempTable FROM (SELECT * FROM
(
SELECT [date_],[issue_id],[cusip],[Factor_value],[factor_label]
FROM [TEMP_lacp_factors]
)t
PIVOT (MAX([factor_value]) FOR [factor_label]
IN ('+#years+')) AS pvt) X'
EXECUTE (#query)
-- Select everything from the dynamically created table ('tempTable') to see results
Select * from tempTable
I'm not 100% sure what you are doing, so it's just a best guess.

Related

SQL Dynamic Pivot Table Column Order

I have a dynamic pivot table in ms sql server.
The column names are dates and appear in random order.
I would like to order the dates(columns) so they appear chronologically, the oldest being first and the most recent being last so I can trend the data by date.
I cannot figure out how to order the columns.
The date variable name is chartaccessdate.
Any help is appreciated.
Here is my code
declare #columnnames nvarchar(max)=''
declare #sql nvarchar(max)=''
select #columnnames += quotename(chartaccessdate) + ','
from (select distinct chartaccessdate from #temp ) as s
set #columnnames=left(#columnnames,len(#columnnames)-1)
set #sql=
'select * from (
select --phase,
unit,OccupationCode occode
,OccupationCode , chartaccessdate from #temp
) as a
Pivot
( count(OccupationCode)
FOR [chartaccessdate] IN (
'+#columnnames +
'
-- "2021-08-23"
--,"2021-08-24"
--,"2021-08-21"
--,"2021-08-22"
) )as pvt '
execute sp_executesql #sql
Rather than SELECT DISTINCT, one quick option would be:
select top 1000 chartaccessdate from #temp group by chartaccessdate order by 1

Rows to Columns RDLC

i have data in below format. this data is coming through SQL Query.
i want to show it in below format either by query or by rdlc report.
You need to use dynamic SQL to make it.
From your expected result you can try to follow thoes step to make it.
use row_number function make row number by Name, because we need to join base on that row_number.
get the use MAX and MIN to make row number calendar table. from 1 to max(rn). the table can let use outer join
declare a var #tables to make the OUTER JOIN execute SQL (each LEFT JOIN maen a group of Crew#).
declare a var #col to make column, which you want to select (Employee) from each table.
then use execute dynamic execute it.
look like this.
create table T
(
Name varchar(50),
Employee VARCHAR(50)
)
insert into T values ('Crew#1','TR123');
insert into T values ('Crew#1','311');
insert into T values ('Crew#2','DDD');
insert into T values ('Crew#2','12121');
insert into T values ('Crew#1','SDDAS');
insert into T values ('Crew#3','31114312');
insert into T values ('Crew#3','DD14124D');
insert into T values ('Crew#3','1214124121');
insert into T values ('Crew#3','SDD412AS');
DECLARE #tables AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#col AS NVARCHAR(MAX);
SET #tables = STUFF((SELECT distinct ' LEFT JOIN ' + ' (SELECT * FROM CTE WHERE Name = '''+Name+''') '+QUOTENAME(Name)+' on t1.smallRN = '+QUOTENAME(Name)+'.rn'
FROM T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #col = STUFF((SELECT distinct ', ' + QUOTENAME(Name)+'.Employee as '''+ QUOTENAME(Name) +''''
FROM T
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #col = substring(#col,1, len(#col))
set #query = '
WITH CTE AS (
SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Name) rn
FROM T
),CTE1 AS(
SELECT MIN(rn) smallRN,MAX(rn) bigRN
FROM CTE
UNION ALL
SELECT smallRN+1,bigRN
FROM CTE1
WHERE smallRN < bigRN
)
SELECT '+#col+'
FROM CTE1 t1 ' + #tables
execute(#query)
sqlfiddle
Creatin tbale
First we will create a temp table where we will stock the data that you have and your table
create table #table1
(
[Crew Name] varchar(500) ,
Employee varchar(500)
)
INsert into #table1
values (....)
select * from #table1
Dynamic selection
then we will create a dynamic query to get the columns that we have, that way we can add as much crews as we want,
declare #DynamicPivotQuery as nvarchar(max)
declare #ColumnName as nvarchar(max)
select #ColumnName = ISNULL(#ColumnName +',','') + QUOTENAME([Crew Name])
from (select distinct [Crew Name] from #table1) as Country
set #DynamicPivotQuery = N'select ' +#ColumnName + '
from #table1
Pivot ( MAX(Employee)
FOR [Crew Name] in (' +#ColumnName+')) as Pivoted
'
exec (#DynamicPivotQuery)
this way we will get only the first row for every column
so we have to find a way to aggregate and get the other columns as well just to demonstrate i will union the Mmin also this is where i stoped my testes but you can do more then this with some testes
now the union :
declare #DynamicPivotQuery as nvarchar(max)
declare #ColumnName as nvarchar(max)
select #ColumnName = ISNULL(#ColumnName +',','') + QUOTENAME([Crew Name])
from (select distinct [Crew Name] from #table1) as Country
set #DynamicPivotQuery = N'select ' +#ColumnName + '
from #table1
Pivot ( MAX(Employee)
FOR [Crew Name] in (' +#ColumnName+')) as Pivoted
union
select ' +#ColumnName + '
from #table1
Pivot ( MIN(Employee)
FOR [Crew Name] in (' +#ColumnName+')) as Pivoted
'
exec (#DynamicPivotQuery)
here is the result :
if you follow this way i'm sure that you will find a way to union all the result
You can add this result into a temp table
then add a column which will be a reference into this temp table
then use pivot function
To know more about pivot Visit :
https://msdn.microsoft.com/en-us/azure/data-lake-analytics/u-sql/pivot-and-unpivot-u-sql
you can use also SSIS to a very handy tool and easy to use
Using dynamic PIVOT if you dont have a set Crew columns.
DECLARE #ColumnString VARCHAR(256)
DECLARE #ColumnHeadrer VARCHAR(256)
DECLARE #sql varchar(1000)
CREATE TABLE #ColumnValue
(
Value VARCHAR(500),
ColumnHeader VARCHAR(256)
)
INSERT INTO #ColumnValue (Value, ColumnHeader)
SELECT DISTINCT '[' + CrewName + ']',
'ISNULL(' + CrewName + ','''') AS ' + CrewName
FROM CrewTable
SELECT #ColumnString = COALESCE(#ColumnString + ',', '') + Value,
#ColumnHeadrer = COALESCE(#ColumnHeadrer + ',', '') + ColumnHeader
FROM #ColumnValue
SET #sql =
'
SELECT ' + #ColumnHeadrer + '
FROM
(
SELECT Employee,
CrewName,
ROW_NUMBER() OVER(PARTITION BY CrewName ORDER BY CrewName) AS rnk
FROM CrewTable
) AS P
PIVOT
(
MAX(Employee) FOR [CrewName] IN ('+#ColumnString+')
) AS pv
'
EXEC (#sql)

Using Row_number() OVER(partition BY..) along with declaring local variables

I have a sql query, in this sql query I want to select distinct columns irrespective of column first. For other sql query I use Row_number() OVER(partition BY..) and I also need to use inner join. The query in which I want to use row_number and inner join is -
DECLARE #columns NVARCHAR(MAX)
DECLARE #params NVARCHAR(MAX) = '#columns NVARCHAR(MAX) OUTPUT'
DECLARE #sql NVARCHAR(MAX) = 'SELECT #columns = STUFF(
(
SELECT '',''+ [column_name] FROM information_schema.columns
WHERE (table_schema = ''dbo''
AND table_name = ''main_mps_dqs_analog'')
AND (ordinal_position <= 73) FOR XML PATH('''')),1,1,'''')'
EXEC sp_executesql #sql, #params, #columns OUTPUT
SET #sql = 'SELECT '+ #columns + ' FROM dbo.main_mps_dqs_analog WHERE logtime BETWEEN ''2014-10-10 07:17:00'' AND ''2014-10-10 08:47:00'''
EXEC(#sql)
I want to apply inner join of this table with INDUS2_BDS.dbo.ddtable and I want beam_current and logtime of this INDUS2 database table and how to apply partition BY beam_current in this query.
SET #sql = 'SELECT ' + #columns + ' ,AnotherTable.beam_current, RowNumber() Over(Partition By SomeColumn Order By SomeColumn) AS Rn
FROM dbo.TableName join AnotherTable on TableName.SomeColumn = AnotherTable.SomeColumn
WHERE logtime BETWEEN ''2014-10-10 07:17:00'' AND ''2014-10-10 08:47:00'''
I solved it by this sql query with the help from Giorgi

SQL Results data from rows to columns

I have created a query which returns me the following:
[Branch], [SaleDate], [ReceiptNo]
My [SaleDate] column is a concatenation of the SaleMonth and SaleYear in the format '01/2013'
What I require is these results to come out as a form of a table with:
A Column for each [SaleDate]
A Row for each [Branch]
The value for each Row/Column will be a COUNT([ReceiptNo])
Any pointers will be greatly appreciated.
Thanks in advance.
Use the PIVOT table operator:
SELECT *
FROM
(
SELECT ReceiptNo, SaleDate, Branch
FROM tablename
) AS t
PIVOT
(
COUNT(ReceiptNo)
FOR SaleDate IN([01/2013], [02/2013], [03/2013], ...)
) AS p;
SQL Fiddle Demo
To do this dynamically instead of listing the values of SaleDate manually, you have to use dynamic SQL, like this:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME(SaleDate)
FROM tablename
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
SELECT #query = 'SELECT *
FROM
(
SELECT ReceiptNo, SaleDate, Branch
FROM tablename
) AS t
PIVOT
(
COUNT(ReceiptNo)
FOR SaleDate IN(' + #cols + ')) AS p;';
execute(#query);
Updated SQL Fiddle Demo

Create table on SQL Server from dynamic pivot results

Is there a way to directly store the results of a dynamic pivot query into a fixed table? As the result is dynamic I can't create the table by specifying the columnnames and methods like "create table MyTable as (pivot select statement)" seem to fail on SQL server ("Incorrect syntax near the keyword 'AS'").
I have tried to format the SQL below to get a SELECT - INTO - FROM structure but failed to do so. Any help is obviously greatly appreciated!
The SQL used for the pivot is (build thanks to this great website!):
declare #pivot varchar(max), #sql varchar(max)
create table pivot_columns (pivot_column varchar(100))
insert into pivot_columns
select distinct DateField from MyTable order by 1
select #pivot=coalesce(#pivot+',','')+'['+pivot_column+']'from pivot_columns
set #sql = 'SELECT * FROM (select DateField, RefCode, SumField from MyTable) p
PIVOT
(sum(SumField) FOR DateField IN ( ' + #pivot + ') )
AS pvl'
drop table pivot_columns
exec (#sql)
Unless I am not following what you are trying to do you should be able to add the INTO mynewTable to your sql that you are going to execute and you should get the new table.
declare #pivot varchar(max), #sql varchar(max)
create table pivot_columns (pivot_column varchar(100))
insert into pivot_columns
select distinct DateField from MyTable order by 1
select #pivot=coalesce(#pivot+',','')+'['+pivot_column+']'from pivot_columns
set #sql = 'SELECT * INTO mynewTable FROM (select DateField, RefCode, SumField from MyTable) p
PIVOT
(sum(SumField) FOR DateField IN ( ' + #pivot + ') )
AS pvl'
drop table pivot_columns
exec (#sql)
I just test creating a new table in the following script and it gives me a new table that is in the DB for use:
create table t
(
[month] int,
[id] nvarchar(20),
[cnt] int
)
insert t values (4,'TOTAL',214)
insert t values (5,'TOTAL',23)
insert t values (6,'TOTAL',23)
insert t values (4,'FUNC',47)
insert t values (5,'FUNC',5)
insert t values (6,'FUNC',5)
insert t values (4,'INDIL',167)
insert t values (5,'INDIL',18)
insert t values (6,'INDIL',18)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(month)
FROM t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT *
INTO tabletest from
(
select month, id, cnt
from t
) x
pivot
(
sum(cnt)
for month in (' + #cols + ')
) p '
execute(#query)
drop table t

Resources