Pivot Query - SQL Server 2005 - sql

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

Related

SQL Server PIVOT help for dates

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

SQL Server Sort fixed number of rows/columns horizontally

I'm trying use PIVOT in a SQL Server stored procedure to take the following data:
ID Rank
203081 1.1
200761 3.9
202687 5.3
203135 5.0
203090 3.3
and return the ID's sorted horizontally. The ranking goes from 1 to 6 with each rank having tenths in between. Example 1.0, 1.1, 1.2, 1.3, ... 1.9, 2.0
The ID's need to be sorted in order by rank.
The result should return something like the following:
(if additional columns needed for aggregation that is fine as well.)
[1] ,[2] ,[3] ,[4] ,[5]
202687,203135,200761,203090,203081
Using above data the ID's would be sorted by rank as 5.3->5.0->3.9->3.3->1.1
In the end I need to take the results and insert them into another table with the ID's sorted horizontally.
I can't get the PIVOT to work correctly. I'm sure it is something obvious I'm not seeing.
If there is a better/faster way to achieve what is needed I would like to know what that solution would be as well.
It sounds like you just need to use row_number() to get the ordering correct and then PIVOT the data on that row number.
If you have a limited number values then you can use:
select [1], [2], [3], [4], [5]
from
(
select id,
row_number() over(order by [rank] desc) seq
from yourtable
) d
pivot
(
max(id)
for seq in ([1], [2], [3], [4], [5])
) piv;
See SQL Fiddle with Demo
Or if you are going to have an unknown number, you will use dynamic SQL:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(row_number() over(order by [rank] desc))
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
select id,
row_number() over(order by [rank] desc) seq
from yourtable
) x
pivot
(
max(id)
for seq in (' + #cols + ')
) p '
execute sp_executesql #query;
See SQL Fiddle with Demo. These give a result:
| 1 | 2 | 3 | 4 | 5 |
|--------|--------|--------|--------|--------|
| 202687 | 203135 | 200761 | 203090 | 203081 |

SQL Server Query for Many to Many Relationship - how to query?

This is an update to my previous question : Many to many relationship
The previous solution works fine, but now I want tgo improve the results a little bit. I´d like to have all the wavelength values in one row.
So instead of the following result :
DateTimeID Wavelength SensorID
11435 1581,665 334
11435 1515,166 334
11435 1518,286 335
I'd like to have something similar to this:
DateTimeID Wavelength1 Wavelength2 SensorID
11435 1581,665 1515,166 334
11435 1518,286 335
You could use the following which applies a row_number() to the records:
select DateTimeID,
[1] as Wavelength1,
[2] as Wavelength2,
SensorId
from
(
select [DateTimeID], [Wavelength], [SensorID],
row_number() over(partition by DateTimeID, SensorId
order by DateTimeID) rn
from yourtable
) src
pivot
(
max(Wavelength)
for rn in ([1], [2])
) piv
See SQL Fiddle with Demo.
If you will have an unknown number of wavelength values, then you can use dynamic SQL to generate this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME('Wavelength'+cast(rn as varchar(50)))
from
(
select row_number() over(partition by DateTimeID, SensorId
order by DateTimeID) rn
from yourtable
) src
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT DateTimeID,' + #cols + ', SensorId from
(
select [DateTimeID], [Wavelength], [SensorID],
''Wavelength''+cast(row_number() over(partition by DateTimeID, SensorId
order by DateTimeID) as varchar(50)) rn
from yourtable
) x
pivot
(
max(Wavelength)
for rn in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo

SQL rotate rows to columns...dynamic number of rows [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL Server dynamic PIVOT query?
I have a dataset that has the below structure.
CREATE TABLE #TempTable
(
Measure_ID INT,
measurement DECIMAL(18, 4)
)
INSERT INTO #TempTable
VALUES
(1,2.3)
,(1,3.4)
,(1,3.3)
,(2,3)
,(2,2.3)
,(2,4.0)
,(2,4.5)
I need to produce output that will look like this.
1,2.3,3.4,3.3
2,3,2.3,4.0,4.5
Basically its a pivot on Measure_ID. Unfortunately, there can be an unlimited number of measure_id's. So Pivot is out.
I'm hoping to avoid CURSORS, but will if that turns out to be the best approach.
If you have an unknown number of values, then you can use a PIVOT with dynamic SQL:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ','
+ QUOTENAME('Measurement_' + cast(rn as varchar(10)))
from temptable
cross apply
(
select row_number() over(partition by measure_id order by measurement) rn
from temptable
) x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT measure_id, ' + #cols + ' from
(
select measure_id, measurement,
''Measurement_''
+ cast(row_number() over(partition by measure_id order by measurement) as varchar(10)) val
from temptable
) x
pivot
(
max(measurement)
for val in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle With Demo
If you have a known number of values, then you can hard-code the values, similar to this:
SELECT measure_id, [Measurement_1], [Measurement_2],
[Measurement_3], [Measurement_4]
from
(
select measure_id, measurement,
'Measurement_'
+ cast(row_number() over(partition by measure_id order by measurement) as varchar(10)) val
from temptable
) x
pivot
(
max(measurement)
for val in ([Measurement_1], [Measurement_2],
[Measurement_3], [Measurement_4])
) p
See SQL Fiddle With Demo
Both queries will produce the same results:
MEASURE_ID | MEASUREMENT_1 | MEASUREMENT_2 | MEASUREMENT_3 | MEASUREMENT_4
==========================================================================
1 | 2.3 | 3.3 | 3.4 | (null)
2 | 2.3 | 3 | 4 | 4.5

Dynamic pivot table with two id columns

This is probably simple but I"m just not seeing it. Your help is appreciated. I have a table in MS SQLServer that looks like this
CustomerID Time ItemID
1 2008-10-07 06:32:53:00.000 87432
1 2008-10-07 06:32:53:00.000 26413
2 2010-06-23 03:45:10:00.000 6312
2 2011-09-14 07:36:03:00.000 87432
2 2011-09-14 07:36:03:00.000 87432
I want to end up with a table that has each customer, the timestamp and the count of the items purchased during that timestamp, that looks like this
CustomerID Time 87432 26413 6312
1 2008-10-07 06:32:53:00.000 1 1 0
2 2010-06-23 03:45:10:00.000 0 0 1
2 2011-09-14 07:36:03:00.000 2 0 0
In the source table, the time and itemID are variable (and plentiful), so I'm thinking a dynamic pivot will do the trick. Is this possible to do with pivot? If so, how?
You can do this with a dynamic PIVOT. This will count the number of ItemIds that you have for any number of Times.
See a SQL Fiddle with a Demo. This demo leaves the time as a varchar as you stated they were. But this will work if the data is a datetime as well.
Since you want time in the final result, then when you select the columns, you will need to add the time column twice. I called it time1 and time. This allows you to aggregate on time1 in the PIVOT and still have a time column for your final product.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(itemid)
from temp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT customerid, [time], ' + #cols + ' from
(
select customerid, [time] as time1, [time] as [time], itemid
from temp
) x
pivot
(
count([time1])
for itemid in (' + #cols + ')
) p '
execute(#query)
Approach #1 - Click here to see Demo
Declare #ItemIDs varchar(1000) = ''
Declare #Query varchar(8000) = ''
Select #ItemIDs = ISNULL(QuoteName(Convert(varchar, ItemID)) + ',', '')
+ #ItemIDs
From
(
Select distinct ItemID From #MyTable
)K
SET #ItemIDs = SUBSTRING(#ItemIDs,0,len(#ItemIDs))
SET #Query = 'Select CustomerID, [Time],' +
#ItemIDs + ' From
(
Select CustomerID, [Time], ItemID from #MyTable
)K Pivot
(
count(ItemID) FOR ItemID IN (' + #ItemIDs + ')
) AS pvt'
EXEC(#Query)
Approach #2 - Click here to see Demo
Select CustomerID, [Time], [87432] as [87432],
[26413] as [26413], [6312] as [6312] From
(
Select CustomerID, [Time], ItemID from #MyTable
)K Pivot
(
count(ItemID) FOR ItemID IN ([87432] , [26413],[6312])
) AS pvt