CrossTab Query / Pivot Table in MS SQL? - sql

I have a table that has the follow data structure:
terminal | load_time_mns | vehicle
_________________________________________
Terminal 1 | 3 | AA
Terminal 2 | 10 | AF
Terminal 1 | 1 | BF
Terminal 6 | 3 | QRS
Terminal 6 | 1.4 | AA
Terminal 3 | 2.5 | OP
I am trying to get an interval breakdown of load time from each terminal.For example, for the above table, I am trying to create a breakdown that looks like the following:
terminal | [0-1 mns] | [1-2 mns] | [2-3 mns] |
_______________________________________________________________
Terminal 1 | 0 | 1 | 1
_______________________________________________________________
Terminal 2 | 0 | 0 | 0
_______________________________________________________________
Terminal 3 | 0 | 0 | 1
_______________________________________________________________
Terminal 6 | 0 | 1 | 1
After a bit of Googling, it looks like I should be focusing on the pivot() function and crosstab queries. I am reading up on those two, but am still not quite able to get

Something like this might help:
Query 1:
SELECT
terminal,
count(CASE WHEN load_time_mns >= 0 AND load_time_mns < 1 THEN 1 END) [0-1 mns],
count(CASE WHEN load_time_mns >= 1 AND load_time_mns < 2 THEN 1 END) [1-2 mns],
count(CASE WHEN load_time_mns >= 2 AND load_time_mns < 3 THEN 1 END) [2-3 mns]
FROM t
GROUP BY terminal
Results:
| TERMINAL | 0-1 MNS | 1-2 MNS | 2-3 MNS |
|------------|---------|---------|---------|
| Terminal 1 | 0 | 1 | 0 |
| Terminal 2 | 0 | 0 | 0 |
| Terminal 3 | 0 | 0 | 1 |
| Terminal 6 | 0 | 1 | 0 |
Fiddle here.
Note that in your example you did not include 1 in the [0-1] range but you did include 3 in the [0-3] range, which seems not right.

You can use a bit of dynamic SQL to extend this to the complete result set. Create a table called intervals to store the intervals:
Create Table ex (
terminal varchar(10),
load_time_mns decimal(10, 2),
vehicle varchar(3)
);
Insert Into ex values
('Terminal 1', 3, 'AA'),
('Terminal 2', 10, 'AF'),
('Terminal 1', 1, 'BF'),
('Terminal 6', 3, 'QRS'),
('Terminal 6', 1.4, 'AA'),
('Terminal 3', 2.5, 'OP');
Create Table intervals (
min_mns decimal(10, 2),
max_mns decimal(10, 2),
column_name sysname
);
declare #i int = 0
while #i <= 20
begin
insert into intervals values (
#i, #i + 1, convert(varchar, #i) + '-' + convert(varchar, #i + 1)
);
set #i += 1;
end
while #i <= 420
begin
insert into intervals values (
#i, #i + 5, convert(varchar, #i) + '-' + convert(varchar, #i + 5)
);
set #i += 5;
end
You can then use a cursor to build up the complete SQL
declare
#sql nvarchar(max) = N'select terminal',
#lo int, #hi int, #col sysname;
declare pivot_cursor cursor local fast_forward for
select
min_mns, max_mns, column_name
from
intervals
order by
min_mns;
open pivot_cursor;
fetch next from pivot_cursor into #lo, #hi, #col;
while ##fetch_status = 0
begin
set #sql += ', sum(case when load_time_mns >= ' + convert(varchar, #lo)
+ ' and load_time_mns < ' + convert(varchar, #hi)
+ ' then 1 else 0 end) as [' + #col + ']';
fetch next from pivot_cursor into #lo, #hi, #col;
end
close pivot_cursor;
deallocate pivot_cursor;
Set #sql += ' from ex group by Terminal order by terminal';
exec sp_executesql #sql;
Example SQLFiddle

DECLARE #t TABLE ( terminal VARCHAR(10), load_time_mns DECIMAL(5,2), vehicle VARCHAR(3))
INSERT INTO #t ( terminal, load_time_mns, vehicle )
VALUES
('Terminal 1' , 3 , 'AA'),
('Terminal 2' , 10 , 'AF'),
('Terminal 2' , 20 , 'AF'),
('Terminal 1' , 1 , 'BF'),
('Terminal 1' , 25 , 'BF'),
('Terminal 6' , 3 , 'QRS'),
('Terminal 6' , 1.4 , 'AA'),
('Terminal 3' , 2.5 , 'OP')
;WITH intervals AS
(
SELECT m = 0, n = 1
UNION ALL
SELECT CASE WHEN m < 20 THEN m+1 ELSE m+5 END, CASE WHEN n < 20 THEN n+1 ELSE n+5 END
FROM intervals
WHERE n<420
)
SELECT terminal, load_time_mns, vehicle,
interval = CAST(m AS VARCHAR(10)) + '-' + CAST(n AS VARCHAR(10)), m
INTO ##tmp
FROM intervals i
LEFT JOIN #t t
ON t.load_time_mns >= i.m
AND t.load_time_mns < i.n
OPTION (MAXRECURSION 0)
DECLARE #cols VARCHAR(MAX) =
STUFF(CAST((SELECT ',' + QUOTENAME(interval)
FROM (
SELECT DISTINCT interval, m
FROM ##tmp
) t
ORDER BY m
FOR XML PATH(''), TYPE
) AS VARCHAR(MAX)),1,1,'')
DECLARE #sql VARCHAR(MAX) = '
SELECT terminal, ' + #cols + '
FROM (
SELECT terminal, vehicle, interval
FROM ##tmp
) t
PIVOT (
COUNT(vehicle)
FOR interval IN (' + #cols + ')
) p
'
EXEC(#sql)
DROP TABLE ##tmp

Related

How to combine multiple SQL rows into columns dynamically

I have a table with
+-------+-------+-----------------+
| P1_ID | P2_ID | Relationship_ID |
+-------+-------+-----------------+
| 1 | 21 | 3 |
| 1 | 32 | 3 |
| 2 | 45 | 2 |
| 2 | 65 | 1 |
| 3 | 98 | 3 |
| 3 | 94 | 4 |
+-------+-------+-----------------+
I want the final table to look like:
+-------+--------+--------+------+------+
| P1_ID | P2_ID1 | P2_ID2 | RID1 | RID2 |
+-------+--------+--------+------+------+
| 1 | 21 | 32 | 3 | 3 |
| 2 | 45 | 65 | 2 | 1 |
| 3 | 98 | 94 | 3 | 4 |
+-------+--------+--------+------+------+
I am not sure which direction to go with this. I am trying to use a pivot but I can not seem to make it work. Maybe I am doing it wrong.
You can use conditional aggregation for this. This isn't exactly what you stated for output because the ordering of your data is a little funky. But this should point you in the right direction.
declare #Something table
(
P1_ID int
, P2_ID int
, Realationship_ID int
)
insert #Something values
(1,21,3)
, (1,32,3)
, (2,45,2)
, (2,65,1)
, (3,98,3)
, (3,94,4)
select P1_ID
, P2_ID1 = MAX(Case when RowNum = 1 then P2_ID end)
, P2_ID2 = max(case when RowNum = 2 then P2_ID end)
, RID1 = MAX(Case when RowNum = 1 then Realationship_ID end)
, RID2 = max(case when RowNum = 2 then Realationship_ID end)
from
(
select *
, RowNum = ROW_NUMBER() over(partition by s.P1_ID order by Realationship_ID)
from #Something s
) x
group by x.P1_ID
--EDIT--
Here is a fully dynamic solution for this. I switched to using a temp table because a table variable would be out of scope for dynamic sql. Obviously in your situation you would be using a persistent table. This will order the output by P1_ID and the columns within each row by Realationship_ID.
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
P1_ID int
, P2_ID int
, Realationship_ID int
)
insert #Something values
(1,21,3)
, (1,32,3)
, (2,45,2)
, (2,65,1)
, (3,98,3)
, (3,94,4)
;
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by P1_ID order by P1_ID';
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *
, RowNum = ROW_NUMBER() over(partition by s.P1_ID order by Realationship_ID)
from #Something s
)
select P1_ID';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a cross join E1 b), --10E+2 or 100 rows
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then P2_ID end) as P2_ID' + CAST(N as varchar(6)) + CHAR(10) +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Realationship_ID end) as RID' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by P1_ID
order by COUNT(*) desc
)
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute

SQL - Getting Percent Difference from dynamic SQL

I currently have a dynamic stored procedure that takes every month in my database and averages out the values per day.
What I currently have (values are the overall average for that month):
+-------------------------------------------------------+
| ID | CustName | 201501 | 201502 | 201503 | 201504 | ..|
+-------------------------------------------------------+
| 32 | CustOne | 5852.25| 5847.50| 6542.98| 7585.25| ..|
| 56 | CustTwo | 5452.45| 7852.50| 6985.41| 1245.21| ..|
| 89 | CustThree| 8520.25| 7410.01| 9630.36| 1245.32| ..|
| .. | ... | .. | .. | .. | .. | ..|
+-------------------------------------------------------+
This is the stored procedure I'm using to create the above table:
DECLARE #Dates NVARCHAR(MAX);
SELECT #Dates = CONCAT(#Dates + ', ', QUOTENAME(BalMonth))
FROM vAvgMonBal
GROUP BY BalMonth
ORDER BY BalMonth;
DECLARE #DynSQL NVARCHAR(MAX),
#months NVARCHAR(MAX);
SET #months = 'CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate)))) AS BalMonth'
SET #DynSQL = 'SELECT *
FROM
(SELECT
a1.IDNbr,
a2.CustName, ' + #months + ',
AVG(a1.Balance) as Balance
FROM tblID a1
INNER JOIN tblCust a2 ON (a1.IDNbr = a2.IDNbr)
WHERE a2.CustType != ''Inactive''
GROUP BY
a1.IDNbr, a2.CustName, CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate))))) as d1
PIVOT (
AVG(Balance)
FOR BalMonth IN (' + #Dates + ')
) piv';
EXECUTE sp_executesql #DynSQL
Question: how can I take the data from the previous stored procedure and get the percent difference, (Month1/Month2) * 100, from it like shown below? I'm expecting I'll need a new stored procedure or add on to the one I currently have.
What I'm needing (where each "PerDiff" is the percent difference of the previous month from the before table example):
+---------------------------------------------------------------+
| ID | CustName | PerDiff1 | PerDiff2 | PerDiff3 | PerDiff4 | ..|
+---------------------------------------------------------------+
| 32 | CustOne | 100.00 | 68.12 | 654.25 | 483.36 | ..|
| 56 | CustTwo | 58.21 | 154.54 | 932.45 | 58.45 | ..|
| 89 | CustThree| 965.25 | 951.58 | 689.12 | 32.50 | ..|
| .. | ... | .... | .... | .... | .... | ..|
+---------------------------------------------------------------+
I've attempted to use something like:
DECLARE #PerDiff nvarchar(max);
SET #PerDiff = 'SELECT *
FROM (' + #DynSQL + ')'
EXECUTE sp_executesql #PerDiff
To at least try and get the data moving.
I'm no longer getting any error messages-- I'm generally just stuck on how to proceed with getting the math to be applied dynamically.
Any help or advice would be greatly appreciated!
EDIT1: Here is the result of finalized #DynSQL
SELECT *
FROM
(
SELECT a1.DDANbr,
a2.CustName,
CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), '0' + CONVERT(nvarchar(15), MONTH(BalDate))))AS BalMonth,
a1.Balance
FROM tblID a1 INNER JOIN tblCust a2 ON (a1.IDNbr = a2.IDNbr)
WHERE a2.CustType != 'Inactive'
GROUP BY a1.IDNbr, a2.CustName, BalDate, a1.Balance
) as d1
PIVOT (
AVG(Balance)
FOR BalMonth IN ([201501], [201502], [201503], [201504], [201505], [201506], [201507], [201508], [201509], [201510], [201511], [201512], [201601], [201602], [201603], [201604], [201605], [201606], [201607], [201608], [201609], [201610], [201611], [201612], [201701], [201702], [201703], [201704], [201705], [201706], [201707], [201708], [201709], [201710], [201711], [201712], [201801], [201802], [201803], [201804], [201805], [201806], [201807], [201808], [201809])
) piv
When you take a query and make it a derived table, you have to give that table an alias.
Like this:
DECLARE #PerDiff nvarchar(max);
SET #PerDiff = 'SELECT IDNbr, CustName, ' + #months + '
FROM (' + #DynSQL + ') t1'
EXECUTE sp_executesql #DynSQL, #PerDiff
DECLARE #Dates NVARCHAR(MAX);
SELECT #Dates = CONCAT(#Dates + ', ', QUOTENAME(BalMonth))
FROM vAvgMonBal
GROUP BY BalMonth
ORDER BY BalMonth;
DECLARE #DynSQL NVARCHAR(MAX),
#months NVARCHAR(MAX);
SET #months = 'CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate)))) AS BalMonth'
SET #DynSQL = 'SELECT *
FROM
(SELECT
a1.IDNbr,
a2.CustName, ' + #months + ',
AVG(a1.Balance) as Balance
FROM tlbID a1
INNER JOIN tblCust a2 ON (a1.IDNbr = a2.IDNbr)
WHERE a1.Balance != 0.00
AND a2.CustType != ''Inactive''
GROUP BY
a1.IDNbr, a2.CustName, CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate))))) as d1
PIVOT (
AVG(Balance)
FOR BalMonth IN (' + #Dates + ')
) piv';
EXECUTE sp_executesql #DynSQL

SQL Count Report Query

I have following table in SQL Server.
Test.
id | Author| Ext
----+-------+--------
01 | Bill | txt
02 | Tom | pdf
03 | Bill | doc
04 | Alex | txt
05 | Alex | pdf
06 | Tom | pdf
I want following to be output based on id.
| Author| txt | pdf | doc
--------+-----+-----+-----
| Bill | 1 | 0 | 1
| Tom | 0 | 2 | 0
| Alex | 1 | 1 | 0
Can anyone suggest me query for the same?
Use CASE expression.
Query
select [Author],
sum(case [Ext] when 'txt' then 1 else 0 end) as [txt],
sum(case [Ext] when 'pdf' then 1 else 0 end) as [pdf],
sum(case [Ext] when 'doc' then 1 else 0 end) as [doc]
from [your_table_name]
group by [Author];
If you want Ext column value to be dynamic, you can use dynamic query string.
Example :
CREATE TABLE Table1
(id int, author varchar(100), ext varchar(3));
INSERT INTO Table1
(id, author, ext)
VALUES
(1, 'Bill', 'txt'),
(2, 'Tom', 'pdf'),
(3, 'Bill', 'doc'),
(4, 'Alex', 'txt'),
(5, 'Alex', 'pdf'),
(6, 'Tom', 'pdf')
Query 1:
DECLARE #MyCursor CURSOR
DECLARE #SQLString NVARCHAR(MAX)
DECLARE #MyField VARCHAR(30)
SET #SQLString = 'SELECT author '
SET #MyCursor = CURSOR FOR
SELECT ext FROM Table1 group by ext
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQLString = #SQLString + ',sum(case [ext] when ''' + #MyField + ''' then 1 else 0 end) as ' + #MyField
FETCH NEXT FROM #MyCursor
INTO #MyField
END
CLOSE #MyCursor
DEALLOCATE #MyCursor
SET #SQLString = #SQLString + ' FROM Table1 group by author'
EXECUTE sp_executesql #SQLString
Results:
| author | doc | pdf | txt |
|--------|-----|-----|-----|
| Alex | 0 | 1 | 1 |
| Bill | 1 | 0 | 1 |
| Tom | 0 | 2 | 0 |
Use below pivot method :
CREATE TABLE #Temp ( id VARCHAR(10) , Author VARCHAR(10), Ext VARCHAR(10) )
INSERT INTO #Temp ( id , Author , Ext )
SELECT 01,'Bill','txt' UNION ALL
SELECT 02,'Tom','pdf' UNION ALL
SELECT 03,'Bill','doc' UNION ALL
SELECT 04,'Alex','txt' UNION ALL
SELECT 05,'Alex','pdf' UNION ALL
SELECT 06,'Tom','pdf'
SELECT *
FROM
(
SELECT Author , Ext
FROM #Temp
) A
PIVOT
(
COUNT(Ext) FOR Ext IN ([txt],[pdf],[doc])
) A
Using PIVOT
with a as
(select 1 as a_id,'abc' as author,'txt' as ext from dual
union
select 2 ,'pqr' as author,'pdf' as ext from dual
union
select 3,'abc' as author,'doc' as ext from dual
union
select 4,'lmn' as author,'txt' as ext from dual
union
select 5,'pqr' as author,'pdf' as ext from dual
)
select *
from
( select *
from a
) pivot
( count(ext)
for ext in
('txt' as txt_ext,'pdf' as pdf_ext,'doc' as doc_ext)
);
For this option, i think using pivot is the best way;
Select * FROM(
Select Authot,Ext,Count(Ext) CountExt FROM #temp Group By Authot,Ext
) t
PIVOT(
SUM(CountExt)
FOR EXt IN ([pdf],[txt],[doc])) as pvt
CASE expression should be used as follow:
SELECT
author,
COUNT(CASE WHEN ext = 'txt' THEN 1 END) as txt,
COUNT(CASE WHEN ext = 'pdf' THEN 1 END) as pdf,
COUNT(CASE WHEN ext = 'doc' THEN 1 END) as doc
FROM myTable
GROUP BY author

T-SQL PIVOT on one column to append the others

Given this table (there's always 2 duplicates of Combinations):
Combination Variable Value
-----------------------------
0 a 1
0 b 2
1 c 3
1 d 4
2 e 5
2 f 6
...
I want to query it to get this:
Variable 0 Value 0 Variable 1 Value 1 Variable 2 Value 2 ...
---------------------------------------------------------------------------
a 1 c 3 e 5
b 2 d 4 f 6
I've tried using PIVOT with dynamic query but cannot come up with a satisfying result.
Can somebody please advise?
EDIT: though Ullas solution works perfectly for combination pairs, I was wondering if it's possible to achieve the same result with combination N-uplets (e.g. (0, 0, 0), (1, 1, 1), (2, 2, 2) should result in 3 rows)? I reckon dynamic query is still the way to go, maybe with PIVOT this time.
Use dynamic sql.
I just created one. Don't know how efficient it is.
Query
declare #query1 varchar(max);
declare #query2 varchar(max);
select #query1 = 'select ' +
STUFF
(
(
select distinct
',min(t.Variable' + cast(Combination as varchar(6)) + ') as Variable' +
cast(Combination as varchar(6)) +
',min(t.Value' + cast(Combination as varchar(6)) + ') as Value' +
cast(Combination as varchar(6))
from tblComb
for xml path('')
),
1,1,'');
select #query1 += ' from('
select #query1 += 'select '+
stuff
(
(
select distinct
',max(case when Combination = ' + cast(Combination as varchar(6)) +'
then Variable end) as Variable' + cast(Combination as varchar(6)) +
',max(case when Combination = ' + cast(Combination as varchar(6)) +'
then Value end) as Value' + cast(Combination as varchar(6))
from tblComb
for xml path('')
),
1, 1, '');
select #query1 += ' from tblComb group by Combination, Variable)t union all ';
select #query2 = 'select ' +
STUFF
(
(
select distinct
',max(t.Variable' + cast(Combination as varchar(6)) + ') as Variable' +
cast(Combination as varchar(6)) +
',max(t.Value' + cast(Combination as varchar(6)) + ') as Value' +
cast(Combination as varchar(6))
from tblComb
for xml path('')
),
1, 1, '');
select #query2 += ' from('
select #query2 += 'select '+
stuff
(
(
select distinct
',max(case when Combination = ' + cast(Combination as varchar(6)) +'
then Variable end) as Variable' + cast(Combination as varchar(6)) +
',max(case when Combination = ' + cast(Combination as varchar(6)) +'
then Value end) as Value' + cast(Combination as varchar(6))
from tblComb
for xml path('')
),
1, 1, '');
select #query2 += ' from tblComb group by Combination, Variable)t;';
select #query1 += #query2;
execute(#query1);
Sample table
+-------------+----------+-------+
| Combination | Variable | Value |
+-------------+----------+-------+
| 0 | a | 1 |
| 0 | b | 2 |
| 1 | c | 3 |
| 1 | d | 4 |
| 2 | e | 5 |
| 2 | f | 6 |
+-------------+----------+-------+
Result set
+-----------+--------+-----------+--------+-----------+--------+
| Variable0 | Value0 | Variable1 | Value1 | Variable2 | Value2 |
+-----------+--------+-----------+--------+-----------+--------+
| a | 1 | c | 3 | e | 5 |
| b | 2 | d | 4 | f | 6 |
+-----------+--------+-----------+--------+-----------+--------+

merge rows in a sql query and create additional columns for different information

I have a sql query that is returning a number of customer results.
each customer has a unique ID but may have multiple transactions.
instead of having multiple rows for each customer i would like to have one row and generate multiple columns for the different info.
for example i have:
id | name | purchase price | date
3 | tim | 20 | 08-2-2014
3 | tim | 25 | 08-5-2014
and i want it to read
id | name | purchase price 1 | date 1 | purchase price 2 | date 2
3 | tim | 20 | 08-2-2014 | 25 | 08-5-2014
I have no idea where to start.
This is done using a dynamic cross tab.
For reference: http://www.sqlservercentral.com/articles/Crosstab/65048/
-- build sample data
create table #temp_table(
id int,
name varchar(255),
[purchase price] decimal(10,2),
[date] smalldatetime
)
insert into #temp_table
select 3, 'tim', 20, '20140802' union all
select 3, 'tim', 25, '20140805' union all
select 4, 'joe', 25, '20140801' union all
select 4, 'joe', 25, '20140803' union all
select 4, 'joe', 25, '20140807' union all
select 1, 'bob', 25, '20140811'
declare #sql1 varchar(4000)
declare #sql2 varchar(4000)
declare #sql3 varchar(4000)
declare #max int
declare #counter int
select #counter = 1
select top 1 #max = count(*) from #temp_table group by id order by count(*) desc-- get number of columns
select #sql1 =
'select
id,
name,
'
select #sql3 =
'from(
select
*,
rn = row_number() over(partition by id, name order by [date])
from #temp_table
)t
group by id, name
order by id'
select #sql2 = ''
while #counter <= #max begin
select #sql2 =
#sql2
+ ' max(case when rn = ' + convert(varchar(10),#counter) + ' then [purchase price] else null end) as [purchase price ' + convert(varchar(10),#counter) + '],' + char(10)
+ ' max(case when rn = ' + convert(varchar(10),#counter) + ' then [date] else null end) as [date ' + convert(varchar(10),#counter) + ']'
if #counter <> #max begin
select #sql2 = #sql2 + ','
end
select #sql2 = #sql2 + char(10)
select #counter = #counter + 1
end
print (#sql1 + #sql2 + #sql3)
exec (#sql1 + #sql2 + #sql3)
drop table #temp_table
Sample Data:
id name purchase price date
----------------------------------------
3 tim 20.00 2014-08-02 00:00:00
3 tim 25.00 2014-08-05 00:00:00
4 joe 25.00 2014-08-01 00:00:00
4 joe 25.00 2014-08-03 00:00:00
4 joe 25.00 2014-08-07 00:00:00
1 bob 25.00 2014-08-11 00:00:00
Result:
id name purchase price 1 date 1 purchase price 2 date 2 purchase price 3 date 3
--------------------------------------------------------------------------------------------------------------------------------------------
1 bob 25.00 2014-08-11 00:00:00 NULL NULL NULL NULL
3 tim 20.00 2014-08-02 00:00:00 25.00 2014-08-05 00:00:00 NULL NULL
4 joe 25.00 2014-08-01 00:00:00 25.00 2014-08-03 00:00:00 25.00 2014-08-07 00:00:00