How to arrange the columns of an SQL pivot table in ascending order - sql

Can someone help me in arranging the columns in ascending order.
My output of pivot table is like:
Ref role_name offer_id 10000 104000 8000 8400
43132_43282 Call Center 1 1 0 0 6
43132_43282 Others 1 2 0 0 3
Instead I want it to be like:
Ref role_name offer_id 8000 8400 10000 104000
43132_43282 Call Center 1 0 6 1 0
43132_43282 Others 1 0 3 2 0
DECLARE #cols AS NVARCHAR(MAX), -- for pivot
#cols2 AS NVARCHAR(MAX), -- for select
#query AS NVARCHAR(MAX);
SET #cols = STUFF((
SELECT DISTINCT ',' + QUOTENAME(c.[Offer_cover])
FROM #cover2 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
-- this is for the SELECT
SET #cols2 = STUFF((
SELECT DISTINCT ',' + 'ISNULL(' + QUOTENAME(c.[Offer_cover]) + ', 0) ' + QUOTENAME(c.[Offer_cover])
FROM #cover2 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = 'SELECT Ref,role_name,offer_id, ' + #cols2 + ' from
(
select *
from #cover2
) x
pivot
(
SUM(cover_earning_Count)
for [Offer_cover] in (' + #cols + ')
) p'
EXECUTE (#query)

Can you add the GROUP BY, ORDER BY [Offer_cover] in the #cols2 variable selection and remove the DISTINCT.
So the query will be:
SET #cols2 = STUFF((
SELECT ',' + 'ISNULL(' + QUOTENAME(c.[Offer_cover]) + ', 0) ' + QUOTENAME(c.[Offer_cover])
FROM #cover2 c
GROUP BY c.[Offer_cover] -- changes here
ORDER BY c.[Offer_cover] -- changes here
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
it will return the #cols2 in the ascending order, so it will impact in the final result.

Related

Sql Pivoting on date

I am getting this error when trying to convert the below logic in to SQL query
Logic:
TRANSFORM First([SirName] & " - " & [SecondName]) AS Name
SELECT qry_Date.RoomNumber
FROM Guest RIGHT JOIN qry_Date ON Guest.ID = qry_Date.GuestID
WHERE (((qry_Date.RoomNumber) Is Not Null))
GROUP BY qry_Date.RoomNumber
PIVOT qry_Date.Date;
Below is what i have done so far
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #query AS VARCHAR(MAX)
SELECT #cols = STUFF((SELECT distinct top 100 percent
',' + QUOTENAME(convert(NVARCHAR(MAX),qry_Date.Date,103))
FROM qry_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'');
SET #query = 'SELECT Name, ' + #cols + '
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Name
,qry_Date.RoomNumber
,qry_Date.Date
FROM Guest RIGHT JOIN qry_DateTemp ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(count(Name) FOR [Date] IN( ' + #cols + ')
) as p'
print #query
execute(#query)
Which results error
Msg 8114, Level 16, State 1, Line 9 Error converting data type
nvarchar to datetime2. Msg 473, Level 16, State 1, Line 9 The
incorrect value "13/12/2014" is supplied in the PIVOT operator. Msg
207, Level 16, State 1, Line 1 Invalid column name 'Name'.
My print #query output
SELECT Name, [01/12/2014],[02/12/2014],[03/12/2014],[04/12/2014],[05/12/2014],[06/12/2014],[07/12/2014],[08/12/2014],[09/12/2014],[10/12/2014],[11/12/2014],[12/12/2014],[13/12/2014],[14/12/2014],[15/12/2014],[16/12/2014],[17/12/2014],[18/12/2014],[19/12/2014],[20/12/2014],[21/12/2014],[22/12/2014],[23/12/2014],[24/12/2014],[25/12/2014],[26/12/2014],[27/12/2014],[28/12/2014],[29/12/2014],[30/12/2014],[31/12/2014]
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Name
,qry_Date.RoomNumber
,qry_Date.Date
FROM Guest RIGHT JOIN qry_Date ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(count(Name) FOR [Date] IN( [01/12/2014],[02/12/2014],[03/12/2014],[04/12/2014],[05/12/2014],[06/12/2014],[07/12/2014],[08/12/2014],[09/12/2014],[10/12/2014],[11/12/2014],[12/12/2014],[13/12/2014],[14/12/2014],[15/12/2014],[16/12/2014],[17/12/2014],[18/12/2014],[19/12/2014],[20/12/2014],[21/12/2014],[22/12/2014],[23/12/2014],[24/12/2014],[25/12/2014],[26/12/2014],[27/12/2014],[28/12/2014],[29/12/2014],[30/12/2014],[31/12/2014])
) as p
One quick way to deal with this error is to convert all data to varchar(max) in same manner. After all dates will become header, so it should be string.
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #query AS VARCHAR(MAX)
SELECT #cols = STUFF((SELECT distinct top 100 percent
',' + QUOTENAME(CAST(qry_Date.Date AS NVARCHAR(MAX)))
FROM qry_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'');
SET #query = 'SELECT RoomNumber, ' + #cols + '
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Name
,qry_Date.RoomNumber
,CAST(qry_Date.Date AS NVARCHAR(MAX)) as [Date]
FROM Guest RIGHT JOIN qry_DateTemp ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(count(Name) FOR [Date] IN( ' + #cols + ')
) as p'
print #query
execute(#query)
#DhruvJoshi did it as u Proposed and true i was in error. when i got my results i had to change the query to
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #query AS VARCHAR(MAX)
SELECT #cols = STUFF((SELECT distinct top 100 percent
',' + QUOTENAME(CAST(qry_Date.Date AS NVARCHAR(MAX)))
FROM qry_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'');
SET #query = 'SELECT RoomNumber, ' + #cols + '
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Names
,qry_Date.RoomNumber
,CAST(qry_Date.Date AS NVARCHAR(MAX)) as [Date]
FROM Guest RIGHT JOIN qry_Date ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(MAX([Names]) FOR [Date] IN( ' + #cols + ')
) as p'
print #query
execute(#query)

Row and column total in dynamic pivot in MS SQL Server 2008 my questions is row total and columns total) for all products when add

I have this stored procedure:
USE [Baxe]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CreateTable]
AS
BEGIN
DECLARE #cols AS nvarchar( max) ,
#query AS nvarchar( max);
SET #cols = STUFF(( SELECT DISTINCT ',' + QUOTENAME( bmarke)
FROM subbuyer FOR XML PATH( '' ) , TYPE ).value( '.' , 'NVARCHAR(MAX)') , 1 , 1 , '');
SET #query = 'SELECT bdate, ' + #cols + ' from ( select bdate, bprice as q , bmarke from subbuyer ) x
pivot ( SUM(q)for bmarke in (' + #cols + ') ) p ';
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), bmarke, 120))
from subbuyer
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
PRINT #query;
PRINT #cols;
EXECUTE ( #query );
end
Which gives me this output:
Last row with TOTAL is what I need to add. How can I do this?
Put your query in CTE or temp table and use GROUP BY ROLLUP:
;WITH cte AS (
--your query here
)
SELECT ISNULL(bdate,'TOTAL') bdate,
SUM(Total) Total,
SUM(ACCESSORIES) ACCESSORIES,
SUM(NBB) NBB,
SUM(UNDERWARE) UNDERWARE
FROM cte
GROUP BY ROLLUP (bdate)
Output:
bdate Total ACCESSORIES NBB UNDERWARE
13/04/2016 7000 7000 NULL NULL
14/04/2016 3000 NULL NULL 3000
15/04/2016 3000 NULL NULL 3000
16/04/2016 3000 NULL 3000 NULL
17/04/2016 23000 14000 6000 3000
TOTAL 39000 21000 9000 9000
EDIT#1
Based on sample you provided. You need to add variable with column names with SUM function:
DECLARE #sumcols nvarchar(max)
SET #sumcols = STUFF(( SELECT DISTINCT ', SUM(' + QUOTENAME( bmarke)+') as ' + QUOTENAME(bmarke)
FROM subbuyer FOR XML PATH( '' ) , TYPE ).value( '.' , 'NVARCHAR(MAX)') , 1 , 1 , '');
And change your dynamic query, so your previous query will be in sub-query:
--Forgot about two quotes around TOTAL
SET #query = 'SELECT ISNULL(bdate,''TOTAL'') bdate, '+#sumcols + ' FROM (
SELECT bdate, ' + #cols + ' from ( select bdate, bprice as q , bmarke from subbuyer ) x
pivot ( SUM(q)for bmarke in (' + #cols + ') ) p
) t GROUP BY ROLLUP (bdate)';
Hope this helps.
EDIT#2
To add TOTAL column use:
DECLARE #pluscols nvarchar(max)
SET #pluscols = STUFF(( SELECT DISTINCT '+' + QUOTENAME( bmarke)
FROM subbuyer FOR XML PATH( '' ) , TYPE ).value( '.' , 'NVARCHAR(MAX)') , 1 , 1 , '') + ' as [TOTAL]';
And change your dynamic query, so your previous query will be in sub-query:
--Forgot about two quotes around TOTAL
SET #query = 'SELECT ISNULL(bdate,''TOTAL'') bdate, '+#sumcols + ', SUM([TOTAL]) as [TOTAL] FROM (
SELECT bdate, ' + #cols + ', ' + #pluscols + ' from ( select bdate, bprice as q , bmarke from subbuyer ) x
pivot ( SUM(q)for bmarke in (' + #cols + ') ) p
) t GROUP BY ROLLUP (bdate)';
and this is my producer
use baxe
DECLARE #cols AS nvarchar( max) ,
#query AS nvarchar( max);
SET #cols = STUFF(( SELECT DISTINCT ',' + QUOTENAME( bmarke)
FROM subbuyer FOR XML PATH( '' ) , TYPE ).value( '.' , 'NVARCHAR(MAX)') , 1 , 1 , '');
SET #query = 'SELECT ISNULL(bdate,''TOTAL'') bdate, '+#cols + ' FROM (SELECT bdate, ' + #cols + ' from ( select bdate, bprice as q , bmarke from subbuyer ) x
pivot ( SUM(q)for bmarke in (' + #cols + ') ) p;
) GROUP BY ROLLUP (bdate)';
PRINT (#query )
PRINT (#cols)
EXEC (#query)

Returning "0" for NULL values within Dynamic Pivot for SQL Server

I have the following Code:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(month)
from PRCombinedRM
group by month,AccountNumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT AccountNumber,' + 'FullName,' + 'AccountType,' + 'Company,' + 'AccountBalance,' + #cols + ' from
(
select AccountNumber,
FullName,
AccountType,
Company,
AccountBalance,
month,
amount
from PRCombinedRM
) x
pivot
(
sum(amount)
for month in (' + #cols + ')
) p '
execute(#query)
However currently the results that this is outputting shows the values for "amount" as a NULL, however I would like to replace the NULL values with "0" instead.
How would I go about doing this?
Currently the data outputs as such:
AccountNumber FullName AccountType Company AccountBalance Aug Jul Jun Sep
100 M R Test Test Account Test Company 100 -50 -50 NULL -50
However I would like the data to output as:
AccountNumber FullName AccountType Company AccountBalance Aug Jul Jun Sep
100 M R Test Test Account Test Company 100 -50 -50 0 -50
Thank you.
I would use another variable to store the ISNULL(someColumn,0):
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX);
DECLARE #cols2 AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(month)
from PRCombinedRM
group by month,AccountNumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET #cols2 = STUFF((SELECT distinct ', ISNULL(' + QUOTENAME(month) + ',0) ' + QUOTENAME(month)
from PRCombinedRM
group by month,AccountNumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
set #query = 'SELECT AccountNumber,' + 'FullName,' + 'AccountType,' + 'Company,' + 'AccountBalance,' + #cols2 + ' from
(
select AccountNumber,
FullName,
AccountType,
Company,
AccountBalance,
month,
Amount
from PRCombinedRM
) x
pivot
(
sum(amount)
for month in (' + #cols + ')
) p ';
execute(#query);
You can change the #cols definition:
SET #cols = STUFF((SELECT distinct ', coalesce(' + QUOTENAME(month) ', 0) as ' + QUOTENAME(month)
from PRCombinedRM
group by month,AccountNumber
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 2,'')

Dynamic Pivot Error in sql server

I used the above code from the link. But I recieve an error as
Msg 8156, Level 16, State 1, Line 14 The column 'Factory' was
specified multiple times for 'p'
Efficiently convert rows to columns in sql server
Here is my table :
TEST
ID score Check TotalofScore
------ ----- ------- ------------
867439 1 factory 1
867439 1 Plant 1
867442 1 factory 1
867442 1 Plant 1
923991 1 Warehouse 1
923991 1 Plant 1
923930 1 factory 1
923930 1 Plant 1
923101 1 Warehouse 1
923101 1 Plant 1
Here's my try
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check],
[ID]
ORDER BY [ID]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT ' + #cols + N' from
(SELECT TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM TEST) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N') ) p '
EXEC Sp_executesql #query;
Expected Result :
ID TotalofScore factory Plant Warehouse
------ ------------ ------- ----- ---------
867439 1 1
867439 1 1
867442 1 1
867442 1 1
923991 1 1
923991 1 1
923930 1 1
923930 1 1
923101 1 1
923101 1 1
As mentioned in Error You cannot specify same column name more than once in Pivot like
..pivot (SUM (T.[score])
for T.[check] in ([factory,[Plant],[factory]..))p
Change your #cols initialization like this
SELECT #cols = Stuff((SELECT DISTINCT ',' + Quotename([check])
FROM TEST
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Or
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Update : To convert the Dynamic Pivot into procedure and insert the result into new table
create procedure dbname.schemaname.DynamicPivotProcedure
as
begin
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT ID, [Total Of Score],' + #cols + N' from
(SELECT TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM TEST) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N') ) p '
EXEC Sp_executesql #query;
end
go
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
begin
DROP TABLE #MyTempTable
end
SELECT * INTO #MyTempTable FROM
OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC dbname.schemaname.DynamicPivotProcedure')
SELECT * FROM #MyTempTable
Remove the Id from GROUP BY and ORDER By clause. So that you get the DISTINCT Check columns.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME([check])
from #Sample
group by [Check]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ID, [Total Of Score], ' + #cols + N' from
(
SELECT
TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM #Sample AS TEST
) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N')
) p '
exec sp_executesql #query;

Sort Rows of Dynamic Pivot Table

I have the following query to dynamically pivot some row information:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT ',' + QUOTENAME(convert(char(50), ScheduleEndTime, 120))
FROM metersNotRead
group by ScheduleEndTime
order by ScheduleEndTime DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ScheduleName, MeterID, CurrentGK,
' + #cols + ' from
(
select ScheduleName, MeterID, CurrentGK, ScheduleEndTime, ''Y'' flag
from metersNotRead
) x
pivot
(
max(flag)
for ScheduleEndTime in (' + #cols + ')
) p
order by ' + #cols +' DESC
'
execute(#query)
It gives me the correct results, but I am wondering how I can sort the rows by the first dynamic column, then the second, and so on, until all dynamic columns have been ordered by.
The results I have now are like this:
ScheduleName MeterID CurrentGK FirstDynamicCol SecondDynamicCol ETC
textName1 exampleID1 -- NULL Y
taxtName2 exampleID2 -- Y NULL
I want them to be like this:
ScheduleName MeterID CurrentGK FirstDynamicCol SecondDynamicCol ETC
textName2 exampleID2 -- Y NULL
taxtName1 exampleID1 -- NULL Y
Try this, put your first column name in its own variable, and order by that only.
DECLARE #cols AS NVARCHAR(MAX), #orderby NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #orderby = STUFF((SELECT ',' + QUOTENAME(convert(char(50), ScheduleEndTime, 120)) + ' desc'
FROM metersNotRead
group by ScheduleEndTime
order by ScheduleEndTime DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #cols = STUFF((SELECT ',' + QUOTENAME(convert(char(50), ScheduleEndTime, 120))
FROM metersNotRead
group by ScheduleEndTime
order by ScheduleEndTime DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ScheduleName, MeterID, CurrentGK,
' + #cols + ' from
(
select ScheduleName, MeterID, CurrentGK, ScheduleEndTime, ''Y'' flag
from metersNotRead
) x
pivot
(
max(flag)
for ScheduleEndTime in (' + #cols + ')
) p
order by ' + #orderby
execute(#query)