Is it possible to exclude some vaules from the PIVOT results.
Referencing this question i would like to know if it is posible to exclude the columns in the Pivot table that has 0 value.
Imagine there is a count of 0 for EventType Meeting, is it possible not to show it at all?
i hope you have implemented following solution from the question
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(EventType)
from dbo.testTable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT year,' + #cols + '
from
(
select EventType,
year = year(date)
from dbo.testTable
) x
pivot
(
count(EventType)
for EventType in (' + #cols + ')
) p '
execute(#query)
if so then you can do following
DECLARE #cols AS NVARCHAR(MAX),
#where AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(EventType)
from dbo.testTable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #where = ' where ' + STUFF((SELECT distinct ' Or ' + QUOTENAME(EventType) + ' <> 0 '
from dbo.testTable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,2,3,'')
set #query = 'SELECT year,' + #cols + '
from
(
select EventType,
year = year(date)
from dbo.testTable
) x
pivot
(
count(EventType)
for EventType in (' + #cols + ')
) p ' + #where
execute(#query)
Related
I have a requirement of creating a view for pivot table
This is my source table
According to my requirement I have created the following pivot table
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(Date)
from Salse_Data
group by Date
order by Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Product,' + #cols + ' from
(
select Product, Date, Salse
from Salse_Data
) x
pivot
(
sum(Salse)
for Date in (' + #cols + ')
) p '
execute(#query);
Output is
I need to create an indexed view(Materialized View) above query
So i used procedure to create the view
CREATE PROCEDURE [dbo].[ProductSalse_By_Year_Proc_4]
AS
BEGIN
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(Date)
from Salse_Data
group by Date
order by Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'CREATE VIEW abcd with schemabinding as SELECT Product,' + #cols + ' from
(
select Product, Date, Salse
from Salse_Data
) x
pivot
(
sum(Salse)
for Date in (' + #cols + ')
) p '
EXECUTE(#query)
END
GO
this execuce without errors but not created the view.
Could you please help on this issue?
Columns are not alphabetic because I can't use "order by" with "distinct".Please help me...
My Query :
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',MAX(CASE WHEN KullaniciAdi = ''' + p.KullaniciAdi + ''' THEN KisiAdi END) AS ' + QUOTENAME(p.KullaniciAdi)
FROM Populer p FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT top 100 ' + #cols + ' FROM ( SELECT KullaniciAdi,KisiAdi,ROW_NUMBER() OVER (PARTITION BY KullaniciAdi ORDER BY EklenmeTarihi) AS RowNum FROM Populer ) x GROUP BY RowNum '
EXECUTE(#query)
Results:
Of course you can. The key is to replace the distinct with group by. Then use order by:
SET #cols = STUFF((SELECT ', MAX(CASE WHEN KullaniciAdi = ''' + p.KullaniciAdi + ''' THEN KisiAdi END) AS ' + QUOTENAME(p.KullaniciAdi)
FROM Populer p
GROUP BY KullaniciAdi
ORDER BY p.KullaniciAdi
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'
), 1, 1, ''
) ;
One way around this is to make your query a derived table:
SELECT * FROM
(SELECT DISTINCT {the rest of your current query}) t
ORDER BY SomeColumn
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(Symbol)
from Opt
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date,' + #cols + ' from
(
select Date, Symbol, Price
from Opt
)x
pivot
(
max(Price)
for Symbol in (' + #cols + ')
) p'
execute(#query);
I get this from the above code:
Symbols(varchar50) Date price quantity
apple 14/11/2016 30 15
banana 14/11/2016 22 20
i need like this
Date apple_price apple_quantity banana_price banana_quantity
14/11/2016 30 15 22 10
from above code i get only price
Just a minor twist to your original. Notice the sub-query/Union All.
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct
',' + QuoteName(Symbol+'_Price')
+ ',' + QuoteName(Symbol+'_Quantity')
From Opt For XML Path('')),1,1,'')
Select #SQL = 'Select Date,' + #SQL + '
From (
Select Date,Item=Symbol+''_Price'',Val=Price From Opt
Union All
Select Date,Item=Symbol+''_Quantity'',Val=Quantity From Opt
) A
Pivot (max(Val) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Date apple_Price apple_Quantity banana_Price banana_Quantity
2016-11-14 30 15 22 20
SELECT *
FROM (
SELECT [TM_UserID],
[FullName],
[Worked_dte],
[Worked_Hours]
FROM #Reporting_User_Timesheet
WHERE [worked_dte] BETWEEN '2014-04-04'
AND '2014-04-06'
) AS sourceTable
Pivot(sum([Worked_Hours]) FOR [Worked_dte] IN ([2014-04-04], [2014-04-05], [2014-04-06])) AS PivotTable
A shot in the dark, obviously, but here's how I understood your question.
First, you need a calendar table to get the dates for the range:
http://www.dbdelta.com/calendar-table-and-datetime-functions/
After that, construct the needed PIVOT query and execute it dynamically:
declare #range_start date, #range_end date;
select #range_start = '20140404', #range_end = '20140406';
declare #collist nvarchar(max);
SET #collist = stuff((select distinct ',' + QUOTENAME(convert(varchar,date,112))
FROM calendar
WHERE Datue BETWEEN #range_start AND #range_end
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
declare #q nvarchar(max);
set #q = '
SELECT *
FROM (
SELECT [TM_UserID],
[FullName],
[Worked_dte],
[Worked_Hours]
FROM #Reporting_User_Timesheet
WHERE [worked_dte] BETWEEN ''' + CONVERT(varchar, #range_start, 112) + '''
AND ''' + CONVERT(varchar, #range_end, 112) + '''
) AS sourceTable
Pivot (
sum([Worked_Hours]) FOR [Worked_dte] IN (' + #collist + ')
) AS PivotTable
';
exec (#q);
This executes correctly: (It is weird that I needed to use '' by the date for it to actually execute)
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.statcolumnname) FROM [85137_PHY_Long_PG] c FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT statdate, ' + #cols + ' from
(
select statdate, statcolumnname, statcolumnvalue
from [85137_PHY_Long_PG]
) x
pivot
(
min(statcolumnvalue)
for statcolumnname in (' + #cols + ')
) p WHERE statdate BETWEEN ''2012-04-01 12:15:00'' AND ''2012-04-01 12:45:00'' ORDER BY statdate'
execute(#query)
Now I want to replace the dates with variables:
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#from AS NVARCHAR(MAX),
#to AS NVARCHAR(MAX);
set #from = '2012-04-01 12:15:00'
set #to = '2012-04-01 12:45:00'
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.statcolumnname) FROM [85137_PHY_Long_PG] c FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT statdate, ' + #cols + ' from
(
select statdate, statcolumnname, statcolumnvalue
from [85137_PHY_Long_PG]
) x
pivot
(
min(statcolumnvalue)
for statcolumnname in (' + #cols + ')
) p WHERE statdate BETWEEN ''+#from+'' AND ''+#to+'' ORDER BY statdate'
execute(#query)
I get the following error:Conversion failed when converting character string to smalldatetime data type
Changing the where statement to the following:
WHERE statdate BETWEEN ''+convert(smalldatetime,#from)+'' AND ''+convert(smalldatetime,#to)+'' ORDER BY statdate'
Still gives me the same error, just can't seem to replace the dates as variables
'' is not weird; it is a notation that enables apostrophes inside varchars.
When concatenating make sure that you are not trying to concatenate anything other than (n)varchars and (n)chars because Sql Server will attempt to convert them to other datatypes; in your case, in smalldatetime. You might avoid this trouble by explicitly converting your parameter dates to nvarchars before/during concatenation, but better solution is to use sp_executesql and parameters.
If you leave parameters inside query:
set #query = 'SELECT statdate, ' + #cols + ' from
(
select statdate, statcolumnname, statcolumnvalue
from [85137_PHY_Long_PG]
) x
pivot
(
min(statcolumnvalue)
for statcolumnname in (' + #cols + ')
) p WHERE statdate BETWEEN #from AND #to ORDER BY statdate'
You can execute it with parameters:
exec sp_executesql #query, N'#from datetime, #to datetime', #from=#from_variable, #to=#to_variable
Where #from_variable and #to_variable are datetime variables defined earlier in batch.
UPDATE:
If your ultimate goal is to wrap this code in stored procedure, here is a template:
create proc MyProc (#dateFrom smalldatetime, #dateTo smalldatetime)
as
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.statcolumnname)
FROM [85137_PHY_Long_PG] c
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT statdate, ' + #cols + ' from
(
select statdate, statcolumnname, statcolumnvalue
from [85137_PHY_Long_PG]
) x
pivot
(
min(statcolumnvalue)
for statcolumnname in (' + #cols + ')
) p WHERE statdate BETWEEN #from AND #to ORDER BY statdate'
exec sp_executesql #query, N'#from smalldatetime, #to smalldatetime', #from=#dateFrom, #to=#dateTo
Herewith the solution:
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#internal_fromdate AS SMALLDATETIME,
#internal_todate AS SMALLDATETIME;
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.statcolumnname) FROM [85137_PHY_Long_PG] c FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #internal_fromdate = '2012-04-01 12:15:00';
set #internal_todate = '2012-04-01 12:45:00';
set #query = 'SELECT statdate, ' + #cols + ' from
(
select statdate, statcolumnname, statcolumnvalue
from [85137_PHY_Long_PG]
) x
pivot
(
min(statcolumnvalue)
for statcolumnname in (' + #cols + ')
) p WHERE statdate BETWEEN #FromDate AND #ToDate ORDER BY statdate'
exec sp_executesql #query, N'#FromDate SMALLDATETIME, #ToDate SMALLDATETIME', #FromDate=#internal_fromdate, #ToDate=#internal_todate
UPDATE
Ok, I have tried the following variations:
create proc MyProc9 (#tableName varchar,#dateFrom smalldatetime, #dateTo smalldatetime)
AS
DECLARE
#cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.statcolumnname)
FROM [85137_PHY_Long_MP] c
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
set #query = 'SELECT statdate, ' + #cols + ' from
(
SELECT statdate, statcolumnname, statcolumnvalue
from #table
) x
pivot
(
min(statcolumnvalue)
for statcolumnname in (' + #cols + ')
) p WHERE statdate BETWEEN #from AND #to ORDER BY statdate'
exec sp_executesql #query, N'#table varchar,#from smalldatetime, #to smalldatetime', #table=#tableName,#from=#dateFrom, #to=#dateTo
Error: Must declare the table variable "#table".
Tried '+#tableName+' in the #query string: Incorrect syntax near '8'.
Tried '+QUOTENAME(#tableName)+' in the #query string: Invalid object name '8'.
Tried ['+#tableName+'] in the #query string: Invalid object name '8'.
Tried QUOTENAME(#table) in the #query string: Invalid object name '8'.
Tried [85137_PHY_Long_MP] in the #query string: Works correctly, just want to replace this.
Tried [#tableName] in the #query string: Invalid object name '#tableName'.
Tried #tableName in the #query string: Must declare the table variable "#tableName".
I don't understand how to resolve the problem