SELECT inside pivot incorrect - sql

SSMS is highlighting that something is wrong on the line FOR urlsByFilm.Media_Type_ID IN...
BEGIN
SELECT urlsByFilm.Film_ID, urlsByFilm.Media_Type_ID, urlsByFilm.Media_File_Name
FROM [dbo].[Film_Media_Item] urlsByFilm
PIVOT
(
MAX(urlsByFilm.Media_File_Name)
FOR urlsByFilm.Media_Type_ID IN (SELECT DISTINCT Media_Type_ID FROM [dbo].[Film_Media_Item])
) AS pivot
WHERE API_ID in (#API_IDs)
END
I cannot run this, can you help?

you can't have SQL expression in the IN clause, you need to specify the values.
MAX(urlsByFilm.Media_File_Name)
FOR urlsByFilm.Media_Type_ID IN
(SELECT DISTINCT Media_Type_ID FROM [dbo].[Film_Media_Item])
You need to use dynamic SQL to achieve what you are doing.
your query would like this, with dynamic SQL
DECLARE #cols NVARCHAR(2000)
SELECT #cols = STUFF(( SELECT DISTINCT
'],[' + Media_Type_ID
[dbo].[Film_Media_Item]
ORDER BY '],[' + Media_Type_ID
FOR XML PATH('')
), 1, 2, '') + ']'
DECLARE #query NVARCHAR(4000)
SET #query = N'SELECT Media_File_Name, '+
#cols +'
FROM
(SELECT urlsByFilm.Film_ID, urlsByFilm.Media_Type_ID, urlsByFilm.Media_File_Name
FROM [dbo].[Film_Media_Item] urlsByFilm)p
PIVOT
(
MAX(urlsByFilm.Media_File_Name)
FOR urlsByFilm.Media_Type_ID IN ( '+
#cols +' )
) AS pvt
WHERE API_ID in (#API_IDs)'
EXECUTE(#query)

Related

SQL Server Convert Rows Into Columns

I have a table like this with 145.695 rows.
SERVER
TAPE
ACS08
M00030L3
ACS08
M00253L3
ACS09
M00580L3
ACS09
M00602L3
ACS10
M00580L4
ACS10
M00602L5
ACS10
M00602L7
Now I want to reach a target table structure like this:
ACS08
ACS09
ACS10
M00030L3
M00580L3
M00580L4
M00253L3
M00602L3
M00602L5
M00602L7
I need help because I dont know how can I do.
You can use dynamic pivot to get the desired results.
First we need to generate the dynamic columns based on the [SERVER] column values and then pivot the values as per the requirement:
DECLARE #cols NVARCHAR(MAX), #query NVARCHAR(MAX);
SET #cols = STUFF((SELECT DISTINCT ','+ QUOTENAME([SERVER])
FROM T FOR XML PATH(''), TYPE
).value('.', 'nvarchar(max)'), 1, 1, ''); --XML way of getting the column values
SET #query = 'SELECT '+#cols+' from
(
SELECT [SERVER], [TAPE], ROW_NUMBER() OVER (PARTITION BY [SERVER] ORDER BY (SELECT NULL)) as RN --We need to add a unique number to select all rows while doing aggregation for the PIVOT
FROM T
)x
PIVOT (max([TAPE]) for [SERVER] in ('+#cols+')
) PVT';
EXECUTE (#query);
Please find the db<>fiddle here.
Try this:
DECLARE #Columns nvarchar(max), #Sql nvarchar(max);
SELECT
#Columns =
STRING_AGG(
'MAX(CASE [Server] WHEN ' + QUOTENAME([Server], '''') + ' THEN [Tape] END) AS ' + QUOTENAME([Server]),
','
) WITHIN GROUP(ORDER BY [Server])
FROM
(
SELECT [Server] FROM T GROUP BY [Server]
) S;
SET #Sql =
'SELECT ' + #Columns + ' FROM
(SELECT [Server], [Tape], ROW_NUMBER() OVER (PARTITION BY [SERVER] ORDER BY [Server]) as RN FROM T) S
GROUP BY RN'
EXEC(#Sql);
Note: STRING_AGG() is supported on SQL Server 2017 and later.

Declare a Table Variable based on dynamic pivot columns statement

I want to declare a table variable and fill it from the pivot with dynamic column to perform join statement.
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
SELECT #cols =
STUFF((SELECT DISTINCT ',' + QUOTENAME(ColName)
FROM [sbs].[ProposalAmounts]
GROUP BY ColName, ProposalID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = N'SELECT ProposalID, ' + #cols + N' from
(select ProposalID, Amount, ColName from [sbs].[ProposalAmounts]) x
PIVOT
(MAX(Amount)for ColName in (' + #cols + N')) p '
EXEC sp_executesql #query;
This is what I've done so far and I'm confused as to how to declare a table variable that has dynamic columns in it.
This is the result of the query above:
And this is the result of the table I want to perform join statement:
Like Jeroen Mostert commented, you need to make everything dynamic.
I would suggest to put the join inside the dynamic query. Instead of a table variable, I use a common table expression.
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
SELECT #cols =
STUFF((SELECT DISTINCT N', ' + QUOTENAME([ColName])
FROM [_tmp_].[ProposalAmounts]
GROUP BY [ColName], [ProposalID]
FOR XML PATH(N''), TYPE).value(N'.', N'NVARCHAR(MAX)'), 1, 2, N'')
SET #query = N'
WITH [CTE_Pivoted_ProposalAmounts] AS
(
SELECT [ProposalID], ' + #cols + N'
FROM
(SELECT [ProposalID], [Amount], [ColName] FROM [sbs].[ProposalAmounts]) x
PIVOT (MAX([Amount]) FOR [ColName] IN (' + #cols + N')) p
)
SELECT *
FROM
[sbs].[OtherTable] ot
INNER JOIN [CTE_Pivoted_ProposalAmounts] ppa ON ppa.[ProposalID] = ot.[ProposalID];
';
EXEC sp_executesql #query;
You need to replace [sbs].[OtherTable] with the actual name of the table you want to join with. And you might also tweak the join criteria and the fields in the SELECT clause. This code here is just a simple example. I assume you will manage to fix the query yourself to make it behave as you expect.

Pivoting Issue (what am I missing)?

Trying to pivot data and add a calculated column to no avail.
I have tried the enclosed code below but cannot get exactly what I am after.
My table consists of three columns
TABLE_NAME, REPORT_DATE, COUNT_ROWS
For the last two [REPORT_DATE]s, I am trying to show in a pivot the [COUNT_ROWS] for each [TABLE_NAME]
What am I missing? Additionally, how would I go about adding a column subtracting the values between the two dates in the pivot?
DECLARE #cols AS NVARCHAR(MAX)='';
DECLARE #query AS NVARCHAR(MAX)='';
SELECT #cols = #cols + QUOTENAME(REPORT_DATE) + ',' FROM (select DISTINCT TOP 2 REPORT_DATE from account_report order by REPORT_DATE desc) as tmp
select #cols = substring(#cols, 0, len(#cols)) --trim "," at end
set #query =
'SELECT * from
(select [TABLE_NAME], [COUNT_ROWS] from account_report
) src
pivot
(sum([COUNT_ROWS]) for [TABLE_NAME] in (' + #cols + ')
) piv'
execute(#query)
All I am getting from the script is a two column result of the two [REPORT_DATE]s with 1 row showing null values (although my data does include rows)
I bet you are trying to get the following out of the query:
SELECT * from
(select [TABLE_NAME], [COUNT_ROWS], [REPORT_DATE] from account_report
) src
pivot
(sum([COUNT_ROWS]) for [REPORT_DATE] in (' + #cols + ')
) piv
Conversely, if you really want the report name pushed out columnwise then you need to adjust your #cols variable.
SELECT #cols = #cols + QUOTENAME(TABLE_NAME) + ',' FROM (select DISTINCT TOP 2 TABLE_NAME ,REPORT_DATE from account_report order by REPORT_DATE desc) as tmp
select #cols = substring(#cols, 0, len(#cols)) --trim "," at end
set #query =
'SELECT * from
(select [REPORT_DATE], [TABLE_NAME], [COUNT_ROWS] from account_report
) src
pivot
(sum([COUNT_ROWS]) for [TABLE_NAME] in (' + #cols + ')
) piv'
execute(#query)

Dynamic pivot table with multiple columns in sql server

I am trying to pivot table DYNAMICALLY but couldn't get the desired result.
Here is the code to create a table
create table Report
(
deck char(3),
Jib_in float,
rev int,
rev_insight int,
jib_out float,
creation int
)
insert into Report values
('A_1',0.345,0,0,1.23,20140212),
('B_2',0.456,0,4,2.34,20140215),
('C_3',0.554,0,6,0.45,20140217),
('D_4',0.231,0,8,7.98,20140222),
('E_5',0.453,0,0,5.67,20140219),
('F_6',0.344,0,3,7.23,20140223)'
Code written so far.... this pivots the column deck and jib_in into rows but thats it only TWO ROWS i.e the one i put inside aggregate function under PIVOT function and one i put inside QUOTENAME()
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(deck)
FROM (SELECT p.deck FROM dbo.report AS p
GROUP BY p.deck) AS x;
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.deck, p.jib_in
FROM dbo.report AS p
) AS j
PIVOT
(
SUM(jib_in) FOR deck IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
I need all the columns to be pivoted and show on the pivoted table. any help would be appreciated. I am very new at dynamic pivot. I tried so many ways to add other columns but no avail!!
I know there are other ways please feel free to mention if there is any other way to get this right.
Please use this (If you are getting Collation issue, please change all the 3 INT datatypes):
STATIC code:
SELECT HEADER, [A_1],[B_2],[C_3],[D_4],[E_5],[F_6]
FROM
(SELECT DECK,HEADER, VALUE FROM REPORT
UNPIVOT
(
VALUE FOR HEADER IN ([JIB_IN],[REV],[REV_INSIGHT],[JIB_OUT],[CREATION])
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR DECK IN ([A_1],[B_2],[C_3],[D_4],[E_5],[F_6])
) PIV
Using Dynamic SQL:
DECLARE #COLSUNPIVOT AS NVARCHAR(MAX),
#QUERY AS NVARCHAR(MAX),
#COLSPIVOT AS NVARCHAR(MAX)
SELECT #COLSUNPIVOT = STUFF((SELECT ','+QUOTENAME(C.NAME)
FROM SYS.COLUMNS AS C
WHERE C.OBJECT_ID = OBJECT_ID('REPORT') AND C.NAME <> 'DECK'
FOR XML PATH('')), 1, 1, '')
SELECT #COLSPIVOT = STUFF((SELECT ',' + QUOTENAME(DECK)
FROM REPORT T FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
SET #QUERY
= 'SELECT HEADER, '+#COLSPIVOT+'
FROM
(
SELECT DECK,HEADER,VALUE FROM REPORT
UNPIVOT
(
VALUE FOR HEADER IN ('+#COLSUNPIVOT+')
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR DECK IN ('+#COLSPIVOT+')
) PIV'
EXEC(#QUERY)

select from the result of execute(#query)

I am using this SQL query
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Animal2)
from animals
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Animal1, ' + #cols + ' from
(
select animal1, animal2, Corelation
from animals
) x
pivot
(
min(Corelation)
for animal2 in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with demo
When I execute the query I get a table as a return.
How can I select from that table? I tried to use SELECT * FROM (*past here the script*) but it did not work. I just need to use the result of the execute(#query) as a table and select from it (to put it in a new table). How can I do it?
Thanks
NOTE: that query was an answer of this SO question
Use the Insert into ... exec format, like this:
CREATE TABLE #tmp1 (
[Animal1] varchar(5),
[Cat] decimal(10, 5),
[Dog] decimal(10, 5),
[Mouse] decimal(10, 5)
)
Insert Into #Tmp1
execute(#query)
select * from #tmp1
where cat = 1
Of course, since the column names are dynamic, you'll need to shift the create statement to dynamic sql too.
SQL Fiddle with the fixed version
SQL Fiddle with the dynamic version
Use into and a global temporary table - then you don't have to define the table columns in advance.
set #query = 'SELECT Animal1, ' + #cols +
+' into ##temp '
+' from
(
select animal1, animal2, Corelation
from animals
) x
pivot
(
min(Corelation)
for animal2 in (' + #cols + ')
) p '
select * from ##temp