SQL Server PIVOT help for dates - sql

I am having a table that is having data dynamic.
A general example
A B C
04/05/2020 04/05/2020 9:00 04/05/2020 13:00
04/05/2020 04/05/2020 13:30 04/05/2020 17:05
I need to have the data in the same row like
A B C D E
04/05/2020 04/05/2020 9:00 04/05/2020 13:00 04/05/2020 13:30 04/05/2020 17:05
I tried to use PIVOT but that didn't helped me out
any suggestions?

Basically, what Marc said. Here is an example of what it should look like. The though part which is described in Marcs Link is how to make this dynamic as for the PIVOT function, the values need to be defined initially and cannot be dynamic:
CREATE TABLE dbo.Test(
A VARCHAR(10),
B VARCHAR(10),
C VARCHAR(10)
)
INSERT INTO [dbo].[Test]
( [A]
,[B]
,[C]
)
VALUES
(
'A' -- A - VARCHAR
,'B' -- B - VARCHAR
,'C' -- C - VARCHAR
),
(
'A' -- A - VARCHAR
,'B' -- B - VARCHAR
,'C' -- C - VARCHAR
);
SELECT [1], [2], [3], [4], [5], [6], [7], [8], [9]
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY A) AS Id
FROM (
SELECT A, 'Col' AS X FROM dbo.Test
UNION ALL
SELECT B, 'Col' AS X FROM dbo.Test
UNION ALL
SELECT C, 'Col' AS X FROM dbo.[Test] tes
) AS Q
) AS P
PIVOT (MAX(A) FOR Id IN ([1], [2], [3], [4], [5], [6], [7], [8], [9])) AS Pvt

You first should get all your data on a single dataset:
with data as (
select A as value from MyTable
union
select B from MyTable
union
select C from MyTable
)
select value from data order by value
Once you have normalized your data, then you can use a generic solution for converting rows to columns.
Like this one : Efficiently convert rows to columns in sql server
It would look like :
-- Create the sample data
create table MyTable (A datetime, B datetime, C datetime)
insert into MyTable (A, B, C)
values ('04/05/2020', '04/05/2020 9:00', '04/05/2020 13:00'),
('04/05/2020', '04/05/2020 13:30', '04/05/2020 17:05')
-- Normalize the data
;
with data as (
select A as value from MyTable
union
select B from MyTable
union
select C from MyTable
)
select value
into #data
from data
order by value
-- Return rows as columns
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(value)
from #data
order by value
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ' + #cols + N' from
(
select value
from #data
) x
pivot
(
max(value)
for value in (' + #cols + N')
) p '
exec sp_executesql #query;
drop table #data

Related

Dynamic Pivot SQL Server Not Showing Value

I have the following table:
oCode oDateTime oValue
---------------------------------------------
A 2017-01-01 10
B 2017-01-01 20
C 2017-01-01 5
I want to have the following result:
oDateTime A B C
------------------------------------------------
2017-01-01 10 20 5
If Static Pivot, I would use the following code:
select
*
from
(
select
sTag
, sDateTime
, sValue
from #condesarsp
) src
pivot
(
sum(sValue)
for sTag in ([X1], [X2], [X3])
) piv
order by sDateTime;
But unluckily, The oValue is not shown. Its just showing null value. Is there a typo on the code above?
After, I want to have dynamic pivot. So I don't need to define the column, It's just generate from oCode value.
Need help, thank you.
First, you would required to specify max() function rather than sum() and other sTag has value should be [A], [B], [C] rather than [X1]..[X3]
select *
from
(
select
oCode, oDateTime, oValue
from table
) src pivot(
max(oValue)
for ocode in ([A], [B], [C])
) piv
order by 1;
Ya there is some mistakes in your query. You have to give the oCode like A,B,C instead of [X1], [X2], [X3]. Like this:
for sTag in (A, B, C)
So the corrected code is:
select
*
from
(
select
oCode
, oDateTime
, oValue
from condesarsp
) src
pivot
(
sum(oValue)
for oCode in (A, B, C) -- This line is changed.
) piv
order by oDateTime;
Follow the link for demo:
http://sqlfiddle.com/#!18/06a9d/3
Dynamic Query:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.oCode)
FROM condesarsp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT oDateTime, ' + #cols + ' from
(
select oCode
,oDateTime
,oValue
from condesarsp
) x
pivot
(
sum(oValue)
for oCode in (' + #cols + ')
) p '
execute(#query);
Follow the link to the demo:
http://sqlfiddle.com/#!18/06a9d/7

How to get row data in columns and column data in rows using pivot in SQL Server 2008 R2

Current result which I am getting from my stored procedure:
Expected result from current result:
An image only answer to an image only question!
Try this..
Union all with Pivot..
Demo Here
declare #table table
(period nvarchar(10),num int,cost int,value int)
insert into #table
select 'Jan-16',1,100,100
union all select 'Feb-16',2,200,200
union all select 'Mar-16',3,300,300
union all select 'Apr-16',4,400,400
union all select 'May-16',5,500,500
union all select 'Jun-16',6,600,600
union all select 'Jul-16',7,700,700
union all select 'Aug-16',8,800,800
union all select 'Sep-16',9,900,900
union all select 'Oct-16',10,1000,1000
union all select 'Nov-16',11,1100,1100
union all select 'Dec-16',12,1200,1200
--select * from #table
select 'No of Order' as Period,[Jan-16], [Feb-16],[Mar-16],[Apr-16],[May-16],[Jun-16],[Jul-16],[Aug-16],[Sep-16],[Oct-16],[Nov-16],[Dec-16]
from
(
select period,num from #table) u
pivot ( sum(num) for period in ([Jan-16] ,[Feb-16],[Mar-16],[Apr-16], [May-16], [Jun-16],[Jul-16],[Aug-16],[Sep-16],[Oct-16],[Nov-16], [Dec-16]))
as pvt
union all
select 'Cost Of Order' as Period,[Jan-16], [Feb-16],[Mar-16],[Apr-16],[May-16],[Jun-16],[Jul-16],[Aug-16],[Sep-16],[Oct-16],[Nov-16],[Dec-16]
from
(
select period,cost from #table) u
pivot ( sum(Cost) for period in ([Jan-16] ,[Feb-16],[Mar-16],[Apr-16], [May-16], [Jun-16],[Jul-16],[Aug-16],[Sep-16],[Oct-16],[Nov-16], [Dec-16]))
as pvt
union all
select 'Value Of Order' as Period,[Jan-16], [Feb-16],[Mar-16],[Apr-16],[May-16],[Jun-16],[Jul-16],[Aug-16],[Sep-16],[Oct-16],[Nov-16],[Dec-16]
from
(
select period,value from #table) u
pivot ( sum(value) for period in ([Jan-16] ,[Feb-16],[Mar-16],[Apr-16], [May-16], [Jun-16],[Jul-16],[Aug-16],[Sep-16],[Oct-16],[Nov-16], [Dec-16]))
as pvt
Select DaysToManufacture, AVG(StandardCost) As AverageCost
From Production.Product
Group by DaysToManufacture
Here is the result set.
DaysToManufacture AverageCost
0 5.0885
1 223.88
2 359.1082
4 949.4105
No products are defined with three DaysToManufacture.
The following code displays the same result, pivoted so that the DaysToManufacture values become the column headings. A column is provided for three [3] days, even though the results are NULL.
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost
FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;
Here is the result set.
Cost_Sorted_By_Production_Days 0 1 2 3 4
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
My Example:
DECLARE
#v_Columns VARCHAR(MAX),
#v_StartDate DATETIME = '09/15/2015',
#v_EndDate DATETIME = '12/15/2020',
#v_Query VARCHAR(MAX)
SELECT #v_Columns = COALESCE(#v_Columns,'[') + convert(varchar, Date, 101) + '],['
FROM
(SELECT DISTINCT Date FROM view_wc_sessions_info) th
WHERE
th.Date BETWEEN #v_StartDate AND #v_EndDate
SET #v_Columns = SUBSTRING(#v_Columns, 1, LEN(#v_Columns)-2)
SET #v_Query =
'SELECT
*
FROM
(
select [Total], Date, fk_student_rcid
from view_WC_SESSIONS_Info th
WHERE
th.Date BETWEEN ''' + CONVERT(VARCHAR(50), #v_StartDate, 101) + '''
AND ''' + CONVERT(VARCHAR(50), #v_EndDate, 101) + '''
) src
PIVOT
(
COUNT(src.[Total])
FOR src.Date IN (' + #v_Columns + ')
) AS pivotview'
EXEC(#v_Query)

Pivot multiple columns in SQL Server 2008

I am trying to convert column to rows. I am beginner to PIVOT. Tried below code but error is coming as 'Error converting data type nvarchar to datetime.
The incorrect value "Tot_GPS_Cnt" is supplied in the PIVOT operator.'
CREATE TABLE #tbl_Res1
(
CallDate DATETIME,
Tot_GPS_Cnt INT,
Tot_GND_Cnt INT,
Per_Ratio NUMERIC(10,2)
)
INSERT INTO #tbl_Res1
SELECT '2015-04-24 00:00:00.000','40','26','65.00' UNION ALL
SELECT '2015-04-25 00:00:00.000','22','14','63.64' UNION ALL
SELECT'2015-04-26 00:00:00.000','27','21','77.78' UNION ALL
SELECT'2015-04-27 00:00:00.000','41','23','56.10'
Source Table
Desired Output
I have tried with below query bu failing. Please help. Thanks in advance
SELECT CallDate=col, Tot_GPS_Cnt, Tot_GND_Cnt, Per_Ratio
FROM
( select CallDate, col, value from #tbl_Res1
cross apply
(
SELECT 'Tot_GPS_Cnt',cast(Tot_GPS_Cnt as varchar(10)) UNION ALL
SELECT 'Tot_GND_Cnt', cast(Tot_GND_Cnt as varchar(10)) UNION ALL
SELECT 'Per_Ratio', cast(Per_Ratio as varchar(10))
) c (col,value)
) d
PIVOT
(
max(value) for CallDate in ([Tot_GPS_Cnt], [Tot_GND_Cnt], [Per_Ratio])
) as piv
The correct syntax for PIVOT is:
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
Hence, you have to place date values not [Tot_GPS_Cnt], [Tot_GND_Cnt], [Per_Ratio] in place of pivoted columns:
SELECT CallDate=col, [2015-04-24], [2015-04-25], [2015-04-26], [2015-04-27]
FROM
( select CallDate, col, value from #tbl_Res1
cross apply
(
SELECT 'Tot_GPS_Cnt',cast(Tot_GPS_Cnt as varchar(10)) UNION ALL
SELECT 'Tot_GND_Cnt', cast(Tot_GND_Cnt as varchar(10)) UNION ALL
SELECT 'Per_Ratio', cast(Per_Ratio as varchar(10))
) c (col,value)
) d
PIVOT
(
max(value) for CallDate in ([2015-04-24], [2015-04-25], [2015-04-26], [2015-04-27])
) as piv
Thank you #Giorgos Betsos. I just made dynamic solution. Just wanted to share with all.
DECLARE #coldata VARCHAR(500);
DECLARE #sql VARCHAR(MAX);
SELECT #coldata = COALESCE(#coldata + '], [', '') + CONVERT(VARCHAR(10),calldate,110)
FROM #tbl_Res1;
SELECT #coldata = '[' + #coldata +']';
SELECT #coldata;
SET #sql = 'SELECT CallDate=col, ' + #coldata + '
FROM
( SELECT CallDate, col, value FROM #tbl_Res1
cross apply
(
SELECT ''Tot_GPS_Cnt'', CAST(Tot_GPS_Cnt as VARCHAR(10)) UNION ALL
SELECT ''Tot_GND_Cnt'', CAST(Tot_GND_Cnt as VARCHAR(10)) UNION ALL
SELECT ''Per_Ratio'', CAST(Per_Ratio as VARCHAR(10))
) c (col,value)
) d
PIVOT
(
MAX(value) FOR CallDate IN (' + #coldata + ')
) as piv'
SELECT #sql;
EXECUTE (#SQL);

Pivot Query - SQL Server 2005

I have the following query in SQL Server 2005 that fetches the result that is mentioned below it.
select Distinct(date),id,
sum(convert(float,Gross)),
count(*) as no from Daily
group by date,id
order by date desc
Date id Gross Count
2012-11-25 00:00:00.000 Client id1 1232.6140752 12
2012-11-25 00:00:00.000 Client id2 1183.75621528 88
2012-11-26 00:00:00.000 Client id3 4561.459086 67
2012-11-26 00:00:00.000 Client id4 6781.15660608 440
Now how do I get the result in the following format. This looks like a pivot query is reqd please help
id Date1 Date2 Date3 Date4 Date5 Date6 Date7
Client id1 Gross
Client id2 Gross
Client id3 Gross
There are two ways that you can PIVOT, either a static version where you hard-code all of the date values or a dynamic version which will generate the list of dates at run-time.
Static Version:
If you had a limited number of dates your query will be similar to this.
select id, [yourDate1], [yourDate2], [yourDate3]
from
(
select date, id, cast(gross as float) as gross
from Daily
) src
pivot
(
sum(gross)
for date in ([yourDate1], [yourDate2], [yourDate3])
) piv;
See SQL Fiddle with Demo
Dynamic Version:
This version generates dynamic SQL to get the list of dates at run-time. Your code will be similar to this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(date)
from Daily
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT id, ' + #cols + ' from
(
select date, id, cast(gross as float) as gross
from Daily
) src
pivot
(
sum(gross)
for date in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
WITH a AS
(
SELECT [Id], [Gross]
, [DateRank] = DENSE_RANK() OVER (ORDER BY [Date])
FROM [Daily]
)
SELECT *
FROM a PIVOT
(
SUM([Gross])
FOR [DateRank] IN ([1], [2], [3], [4], [5], [6], [7])
) b

SQL Query Dynamic PIVOT [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL Server dynamic PIVOT query?
I have temporary table with following structure:
MONTH ID CNT
----- ----------- ---
4 TOTAL_COUNT 214
5 TOTAL_COUNT 23
6 TOTAL_COUNT 23
4 FUNC_COUNT 47
5 FUNC_COUNT 5
6 FUNC_COUNT 5
4 INDIL_COUNT 167
5 INDIL_COUNT 18
6 INDIL_COUNT 18
How i can get the Pivot over month in this table like:
ID APRIL MAY JUNE
----------- ----- --- ----
TOTAL_COUNT 214 23 23
FUNC_COUNT 47 5 5
INDIL_COUNT 167 18 18
Please consider this table format. I am little messy in posting this format.
I'll leave the conversion of month integers to month names to you, but this will perform the PIVOT for you.
declare #t table
( [month] int, [id] nvarchar(20), [cnt] int )
insert #t values (4,'TOTAL_COUNT',214)
insert #t values (5,'TOTAL_COUNT',23)
insert #t values (6,'TOTAL_COUNT',23)
insert #t values (4,'FUNC_COUNT',47)
insert #t values (5,'FUNC_COUNT',5)
insert #t values (6,'FUNC_COUNT',5)
insert #t values (4,'INDIL_COUNT',167)
insert #t values (5,'INDIL_COUNT',18)
insert #t values (6,'INDIL_COUNT',18)
SELECT
[id], [4], [5], [6]
FROM
(SELECT [month], [id], [cnt] FROM #t) src
PIVOT
(SUM([cnt]) FOR [month] IN ([4], [5], [6])) p
While you can use a Static Pivot - one that you hard-code the months. In the comments, you stated that the number of months maybe be unknown, if that is the case then you will want to use a Dynamic Pivot to generate the list of months. Using a Dynamic Pivot gives you the flexibility of not knowing the columns you need until you run it.
create table t
(
[month] int,
[id] nvarchar(20),
[cnt] int
)
insert t values (4,'TOTAL_COUNT',214)
insert t values (5,'TOTAL_COUNT',23)
insert t values (6,'TOTAL_COUNT',23)
insert t values (4,'FUNC_COUNT',47)
insert t values (5,'FUNC_COUNT',5)
insert t values (6,'FUNC_COUNT',5)
insert t values (4,'INDIL_COUNT',167)
insert t values (5,'INDIL_COUNT',18)
insert t values (6,'INDIL_COUNT',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 id, ' + #cols + ' from
(
select month, id, cnt
from t
) x
pivot
(
sum(cnt)
for month in (' + #cols + ')
) p '
execute(#query)
drop table t
The results would be: