Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Transposing rows to columns

Author  Topic 

tim_buktoo
Starting Member

3 Posts

Posted - 2005-03-14 : 12:42:53
I have a table with 2 fields: ID and Date_visit.

ID Date_visit
101 1/1/01
101 2/1/03
101 3/5/04
102 10/12/03
102 12/15/04

I'd like to transform the data so that it looks like:

ID Date1 Date2 Date3
101 1/1/01 2/1/03 3/5/04
102 10/12/03 12/15/04

After doing so, I can calculate (for each ID) the number of days between date1 and date2, date1 and date3, etc... in a seperate query
So the final query would have 4 fields (ID Date1 Date2 Date3).
Does anyone know the best way to do this. Your help is greatly appreciated.

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-14 : 12:45:37
take a look at:
http://www.sqlteam.com/item.asp?ItemID=2955

Go with the flow & have fun! Else fight the flow
Go to Top of Page

tim_buktoo
Starting Member

3 Posts

Posted - 2005-03-14 : 12:55:30
quote:
Originally posted by spirit1

take a look at:
http://www.sqlteam.com/item.asp?ItemID=2955

Go with the flow & have fun! Else fight the flow



Thanks for the quick reply. I've attempted to create a pivot table in MS Access with the same table, but since I am not using a summary function (SUM(), AVG(), MIN(), MAX())for the dates, it wont work, and I dont want any sums or averages anyway. I want DATE1 to equal the first date (chronologically) it encounters for an ID, DATE2 to equal the next date (chronologically) it encounters, and so on and so forth. So my final product will be a single ID and (for the example provided above) 3 additional (DATE1,2,3) fields that took the stacked dates and put them on the same line.
A pivot table will just count the number of times the date is present for a particular ID. It will not allow me to then compute a datediff on the dates.
I'm not sure that I am being clear. Please let me know if this makes sense.
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2005-03-14 : 14:09:20
If you need the data pivoted, the link spirit1 provided is the way to go. However, run this and see if you can use the format this is providing. Its not pivoted but it will give you a ROW for each subsequent date_visit after the earliest one with the dateDiff as well.

set nocount on
declare @tb Table (ID int, Date_visit smalldatetime)
insert @tb
Select 101, '1/1/2001' union all
Select 101, '2/1/2003' union all
Select 101, '3/5/2004' union all
Select 102, '10/12/2003' union all
Select 102, '12/15/2004'

select a.ID
,b.Date_Visit Date_Visit_1st
,a.Date_Visit
,dateDiff(day, b.Date_Visit, a.Date_Visit) [DateVisitDiff]
From @tb a
JOIN (
Select [id], min(Date_Visit) Date_Visit
From @tb
Group by [id]
) b ON a.[id] = b.[id]
and a.Date_Visit <> b.Date_Visit
Order by 1,2,3


Be One with the Optimizer
TG
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-14 : 15:29:11
this'll help you...
it works only for 2 columns for now.
EDIT: fixed so it works for N columns


create proc spTranspose
@TableName varchar(100),
@PrimaryCol varchar(100), -- parent column to transposing columns
@SecondaryCol varchar(1000) -- CSV string of columns to transpose
as

select @SecondaryCol = replace(@SecondaryCol, ' ', '')

declare @i int, @tInc varchar(10), @tIncNext varchar(10), @Sql varchar(8000),
@SqlSelect varchar(8000), @tempSql nvarchar(4000), @ColNum int

select @i=1, @Sql = '', @SqlSelect = ''

select @tempSql = 'select top 1 @ColNum = count(*) from ' + @TableName + ' group by ' + @PrimaryCol + ' order by 1 desc'

exec sp_executesql @tempSql, N'@ColNum int output', @ColNum output

if object_id('tempdb..##temp_transpose') is not null
drop table ##temp_transpose

exec ('select identity (int, 1,1) as Transpose_Id, ' + @PrimaryCol + ', ' + @SecondaryCol +
' into ##temp_transpose from ' + @TableName + ' order by ' + @PrimaryCol + ', ' + @SecondaryCol)

select @SqlSelect = 'select distinct t1.' + @PrimaryCol,
@Sql = ' from ##temp_transpose t1'

while @i<=@ColNum
begin
set @tInc = 't' + cast(@i as varchar(10))
set @SqlSelect = @SqlSelect + ', ' + @tInc + '.'+ replace(@SecondaryCol, ',', ', ' + @tInc + '.')
set @tIncNext = 't' + cast(@i+1 as varchar(10))
if @i<@ColNum
set @Sql = @Sql + ' LEFT JOIN ##temp_transpose ' + @tIncNext + ' on t1.' + @PrimaryCol + ' = ' + @tIncNext + '.' + @PrimaryCol + ' and ' + @tInc + '.Transpose_Id = ' + @tIncNext + '.Transpose_Id-1 '
set @i = @i + 1
end
exec(@SqlSelect + @Sql + ' WHERE (select count(*) from ##temp_transpose where t1.' + @PrimaryCol + ' = ' + @PrimaryCol + ' and t1.Transpose_Id > Transpose_Id)=0')
go

exec spTranspose 'yourTableName', 'id', 'date_visit,'

/*
use northwind
exec spTranspose 'orders', 'customerId', 'orderDate, shippedDate, employeeid'
*/


Go with the flow & have fun! Else fight the flow
Go to Top of Page

tim_buktoo
Starting Member

3 Posts

Posted - 2005-03-14 : 17:00:19
This works great ! Thanks Spirit1 and TG for your help. It is much appreciated !
Go to Top of Page

dkw2002
Starting Member

2 Posts

Posted - 2005-03-22 : 13:56:36
Can you please tell me how to put the result in a table? Thanks very much!

Dave
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2005-03-22 : 14:28:58
create table #temp (all of the columns you need)
insert into #temp
exec spTranspose 'yourTableName', 'id', 'date_visit,' -- or any other sproc call

for my sproc:
or after calling the sproc you can still acces the data in global ##temp table ##temp_transpose:
select * from ##temp_transpose
because the table gets droped when the sproc runs.


Go with the flow & have fun! Else fight the flow
Go to Top of Page

dkw2002
Starting Member

2 Posts

Posted - 2005-03-22 : 21:21:02
Thanks again!

Dave
Go to Top of Page
   

- Advertisement -