I'm trying to solve experiment with some SQL pivoting. I have created a pivot by naming the columns, I am now trying to do it dynamically. From a few searches I have come up with the following code
USE [LMS]
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(Learning_Path_Title)
FROM (SELECT DISTINCT [Learning_Path_Title] FROM [dbo].[copy from]) AS Courses
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT Distinct [Userd], ' + #ColumnName + '
FROM [dbo].[copy from]
PIVOT(MAX([Learning_Path_Complete])
FOR [Learning_Path_Title] IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
My data is structured in the following way
I want the table to be displayed as below
Related
Im new to Stack overflow and SQL and I'm trying to replicate a function in Microsoft Power Query to use in SQL instead.
I know how to Unpivot and keep 1 Column in SQL and then had to reference all the other columns by name to make the unpivot.
Now I need to Keep 3 ID columns and Unpivot the rest of the columns
(This table has 355 columns right now and will change)
Can anyone help me with this?
This is the furthest I got (Thanks to RAV DBLearning on Youtube), but I cant seem to find a way to Convert the columns types to 1 type.
DECLARE
#SQLSTRING NVARCHAR(MAX),
#COLUMNLIST NVARCHAR(1000) = ''
SELECT
#COLUMNLIST = #COLUMNLIST + QUOTENAME(NAME) + ','
FROM
sys.columns
WHERE
OBJECT_ID = OBJECT_ID('xp.XPROPERTYVALUES') AND
--COLUMN_ID NOT IN(1,2,3)
COLUMN_ID IN(452,453,454)
SELECT
#COLUMNLIST = LEFT(#COLUMNLIST,LEN(#COLUMNLIST)-1)
SET
#SQLSTRING =
'
SELECT
upv.id,
upv.item_id,
upv.itemtype_id,
upv.X_Category,
upv.X_Values
FROM
xp.XPROPERTYVALUES
UNPIVOT
(
X_Values FOR X_Category
IN
(' + #COLUMNLIST + ')
) AS upv
'
PRINT
(#SQLSTRING)
EXECUTE
sp_executesql #SQLSTRING
It just needs a source query.
And you can re-use the calculated column list for that.
DECLARE #SQLSTRING NVARCHAR(MAX),
#COLUMNLIST NVARCHAR(MAX);
DECLARE #TABLENAME VARCHAR(30) = 'xp.XPROPERTYVALUES';
SELECT #COLUMNLIST = CONCAT(#COLUMNLIST + ', ', QUOTENAME(NAME))
FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID(#TABLENAME)
AND LOWER(NAME) NOT LIKE '%id';
SET #SQLSTRING = N'SELECT upv.id
, upv.item_id, upv.itemtype_id
, upv.X_Category, upv.X_Values
FROM
(
SELECT id, item_id, itemtype_id,
'+ #COLUMNLIST + N'
FROM '+ #TABLENAME +N'
) src
UNPIVOT
(
X_Values FOR X_Category IN (' + #COLUMNLIST + N')
) upv';
-- SELECT #SQLSTRING;
EXECUTE sp_executesql #SQLSTRING;
db<>fiddle here
I have a shop order table with the Item code, description ReleaseDate and Required quantity.
How to query in a pivot table format in such a way that the results will be pivoted using Year+Month of [ReleaseDate] in sorting order from oldest date to latest date. Using the Year+Month as a column.
This is my query but it fails.
--Declare necessary variables
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
--Get unique values of pivot column
SELECT #PivotColumns = COALESCE(#PivotColumns + ',','') + QUOTENAME([YEARMONTH])
FROM (SELECT DISTINCT CONVERT(char(6), cast([releaseddate] as date), 112 ) as [YEARMONTH] FROM [dbo].[ShopOrder]) as PivotQuery
SELECT #PivotColumns
--Create the dynamic query with all the values for
--pivot column at runtime
SET #SQLQuery =
N'SELECT ItemCode, ' + #PivotColumns + '
FROM [dbo].[ShopOrder]
PIVOT( SUM(RequiredQty)
FOR [releaseddate] IN (' + #PivotColumns + ')) AS P'
SELECT #SQLQuery
--Execute dynamic query
EXEC sp_executesql #SQLQuery
This is the original record
Results query must be like this
Here I have tried to execute the pivot with your provided data.
Query
Select
[ItemCode],
[Description],
[2017/8],
[2017/9]
from
(
select cast(year(ReleasedDate) as nvarchar)+'/'+cast(month(ReleasedDate) as nvarchar) as ReleasedDate,ItemCode,Description,RequiredQty
from shoporder) as PivotData
Pivot
(
sum(RequiredQty) for ReleasedDate in
([2017/8],[2017/9])) as Pivoting
order by ItemCode
Output:
Fiddle
You are not pivoting correctly and the column names should be generated in a single string. Try this:
CREATE TABLE ShopOrder (ItemCode VARCHAR(100),[Description] VARCHAR(100),ReleaseDate DATE, RequiredQty INT)
GO
INSERT INTO ShopOrder
VALUES
('A','SLEEVE NUT','08/01/2017',19200)
,('A','SLEEVE NUT','08/02/2017',18000)
,('A','SLEEVE NUT','09/01/2017',17000)
,('B','STARTER','08/03/2017',10000)
,('B','STARTER','08/04/2017',18000)
,('B','STARTER','09/15/2017',16000)
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
SET #PivotColumns = STUFF(( SELECT DISTINCT ',[' + CONVERT(char(6), cast(ReleaseDate as date), 112 ) + ']'
FROM ShopOrder
ORDER BY ',[' + CONVERT(char(6), cast(ReleaseDate as date), 112 ) + ']'
FOR XML PATH('')),1,1,'')
SET #SQLQuery =
N'
SELECT ItemCode,'+ #PivotColumns + '
FROM (SELECT ItemCOde,CONVERT(char(6), cast(ReleaseDate as date),112) ReleaseDate, RequiredQty
FROM ShopOrder) AS T
PIVOT( SUM(RequiredQty)
FOR ReleaseDate IN ('+#PivotColumns+')) AS P
'
SELECT #SQLQuery
--Execute dynamic query
EXEC sp_executesql #SQLQuery
I have the following query:
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName = ISNULL(#ColumnName + ',','') + QUOTENAME(MaxDate)
FROM (SELECT DISTINCT MaxDate FROM CustPeriodTable) AS MaxDates
SET #DynamicPivotQuery =
N'SELECT ' + #ColumnName + ' AS Test, min(rn)
FROM CustPeriodTable '
EXEC sp_executesql #DynamicPivotQuery
I'm getting an invalid column name error for every entry in #ColumnName. I'm in the process of setting up a more complicated query that will involve a pivot but I'm trying to get this chunk working first. Can anyone point out where this problem might be coming from?
For these types of issues you need to look at what the dynamic query is. Instead of executing it just select it.
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName = ISNULL(#ColumnName + ',','') + QUOTENAME(MaxDate)
FROM (SELECT DISTINCT MaxDate FROM CustPeriodTable) AS MaxDates
SET #DynamicPivotQuery =
N'SELECT ' + #ColumnName + ' AS Test, min(rn)
FROM CustPeriodTable '
SELECT #DynamicPivotQuery
-- EXEC sp_executesql #DynamicPivotQuery
From here you should be able to determine what the issue is.
I have to write a dynamic pivot based on a complex query and I want to use a common table expression to create the dataset on which I have to build the pivot to keep it outside the dynamic sql and have it compiled
My problem is that I don't know if i can use the CTE in a SET where I wrap the dynamic SQL I have to execute.
let see the code:
WITH DatiCTE AS
(
SELECT ...
)
SET #DynamicPivotQuery =
N'SELECT IdActivity, ' + #PivotSelectColumnNames + '
FROM DatiCTE
PIVOT(SUM(NumOfDays)
FOR Area IN (' + #PivotColumnNames + ')) AS PVTTable'
WHERE 1 = 1
EXEC sp_executesql #DynamicPivotQuery
This way i get an error near SET #DynamicPivotQuery =
If I replace SET with a SELECT the stored procedure is compiled but if i run it I get:
Invalid object name 'DatiCTE'
Move the definition of the CTE WITH DatiCTE AS to be inside the dynamic sql like this:
SET #DynamicPivotQuery =
N'WITH DatiCTE AS
(
SELECT ...
)
SELECT IdActivity, ' + #PivotSelectColumnNames + '
FROM DatiCTE
PIVOT(SUM(NumOfDays)
FOR Area IN (' + #PivotColumnNames + ')) AS PVTTable'
+ 'WHERE 1 = 1';
EXEC sp_executesql #DynamicPivotQuery;
for now i switch to temp table:
SELECT ...
INTO #TempTable
SET #DynamicPivotQuery =
N'
SELECT IdActivity, ' + #PivotSelectColumnNames + '
FROM #TempTable
PIVOT(SUM(NumOfDays)
FOR Area IN (' + #PivotColumnNames + ')) AS PVTTable'
+ 'WHERE 1 = 1';
EXEC sp_executesql #DynamicPivotQuery;
but i have soume doubt about concurrent users. i try table variable but cant be used in dynamic sql...
I am working on a project with SSRS and Rockwell Software's RSView32. Basically this software project logs manufacturing data to individual tables as such:
One table (Machine1_TagTable) has Tag names which describe the data as such: TagName, TagIndex. The name provides a human-understandable reference to the information contained in a second table. Example : Part Number, 1
The second table (Machine1_FloatTable) contains raw data with nothing more than a timestamp, TagIndex and value.
Example : 2013-12-10 15:44:11.322, 1, 12345(value)
I have a dynamic pivot which works for ONE table; however, I would like to use a variable parameter passed from SSRS to select both the TagTable and FloatTable.
This works with the Machine1_FloatTable as part of the dynamic statement, but not in the XML path building. I understand this is a scope issue, so I'm looking for creative ways to allow me to pass the table names from SSRS into this stored procedure.
Here's what I have now:
DECLARE #FLOATTABLE NVARCHAR(MAX), #TAGTABLE NVARCHAR(MAX), #startdate NVARCHAR(MAX),
#enddate NVARCHAR(MAX), #cols as NVARCHAR(MAX), #query as NVARCHAR(MAX)
SET #TAGTABLE ='dbo.Machine1_TagTable'
SET #FLOATTABLE = 'dbo.Machine1_FloatTable'
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(CONVERT(VARCHAR,TagName),'"')
FROM #tagtable
FOR XML PATH('')),1,1,'')
Set #query = 'SELECT DISTINCT DateAndTime, Millitm, ' + #cols + ' FROM ( select
T.DateAndTime, T.Millitm, N.TagName, T.Val from ' + #FLOATTABLE + ' T LEFT JOIN ' +
#TAGTABLE + ' N ON T.TagIndex=N.TagIndex WHERE T.DateAndTime Between '''+ #startdate +
''' AND '''+ #enddate +''') x PIVOT (MAX(Val) for TagName IN (' + #cols + ')) p'
PRINT (#query)
Any help or suggestions would be greatly appreciated. Thanks!
Well, it's possible, if I understand your question. You have to build a dynamic SQL string, and execute that to populate #cols.
declare #string nvarchar(MAX)
set #String = 'SELECT STUFF((SELECT DISTINCT '','' + QUOTENAME(CONVERT(VARCHAR,ActualDate),'
+ '''"'') FROM ' + #TAGTABLE + ' FOR XML PATH ('''')),1,1,'''')'
EXECUTE sp_executeSQL #String, #Cols OUTPUT
print #cols
It's pretty hacky, but I think it should work.