SQL Server Magazine Forums

Spacer
< REFRESH >
Topic Title: Transpose row data into column field
Topic Summary:
Created On: 01/20/2006 11:43 AM

View topic in raw text format.
 01/20/2006 11:43 AM
 User is offline  Print this message

Author Icon
Superman_SQL

Posts: 417
Joined: 04/04/2002

How can I transpose the data from this query into columns. I know I did this before but can't remember how I did it.


SELECT Field1 FROM Table1


Result
------
A
B
C




Want it to return as

A B C

-------------------------
Clark
SQL Elites
    Reply     Quote     Top     Bottom    
 01/20/2006 12:17 PM
 User is offline  Print this message

Author Icon
rm

Posts: 23442
Joined: 04/04/2002

Take look at 'Cross-Tab Reports' in books online.

-------------------------
SQL Server Magazine Forum Pro
    Reply     Quote     Top     Bottom    
 01/20/2006 01:02 PM
 User is offline  Print this message

Author Icon
Superman_SQL

Posts: 417
Joined: 04/04/2002

This is the style that I am currently using. The problem is, the number of records varies from 1 to 100. The example that they provided in BOL is more or less, hard coded on the number of fields.

I am using a loop to build it dynamically and run the t-sql in a EXEC. I am not sure if this is the best practice.


Example from BOL:

SELECT Year,
SUM(CASE Quarter WHEN 1 THEN Amount ELSE 0 END) AS Q1,
SUM(CASE Quarter WHEN 2 THEN Amount ELSE 0 END) AS Q2,
SUM(CASE Quarter WHEN 3 THEN Amount ELSE 0 END) AS Q3,
SUM(CASE Quarter WHEN 4 THEN Amount ELSE 0 END) AS Q4
FROM Northwind.dbo.Pivot
GROUP BY Year
GO


-------------------------
Clark
SQL Elites
    Reply     Quote     Top     Bottom    
 01/20/2006 01:14 PM
 User is offline  Print this message

Author Icon
nosepicker

Posts: 1100
Joined: 11/04/2003

Help us out by giving us more data.
    Reply     Quote     Top     Bottom    
 01/20/2006 01:44 PM
 User is offline  Print this message

Author Icon
Superman_SQL

Posts: 417
Joined: 04/04/2002

Just want to say thank you to RM and Nosepicker for the constant help.

Anyway, I will give a simple example to make easier to read, Nosepicker.

I am going to query against one field in a table. The result set will be something like this:

Field1
-------
A
B
C
D
E

Basing from this data, I just want to create a temp table or even a join of some type to become something like this:

A - B - C - D - E

So, Field1 is "A", Field2 is "B", Field3 is "C" and so on.

Sometime, I might have 5 records, sometime more or less.

Is this the data you are talking about Nosepicker?

-------------------------
Clark
SQL Elites
    Reply     Quote     Top     Bottom    
 01/20/2006 02:24 PM
 User is offline  Print this message

Author Icon
rm

Posts: 23442
Joined: 04/04/2002

May easier to handle that in analysis services.

-------------------------
SQL Server Magazine Forum Pro
    Reply     Quote     Top     Bottom    
 01/20/2006 05:40 PM
 User is offline  Print this message

Author Icon
Superman_SQL

Posts: 417
Joined: 04/04/2002

Can't do it in there because I need to build a table dynamically base on the data.

-------------------------
Clark
SQL Elites
    Reply     Quote     Top     Bottom    
 01/20/2006 06:10 PM
 User is offline  Print this message

Author Icon
nosepicker

Posts: 1100
Joined: 11/04/2003

When I asked for more data, I thought you were going to have other data upon which to base your CASE statements. But I see you just want to flatten a one column table. Perhaps this can work for you:

DECLARE @max_nbr_cols int,
@counter int,
@sql varchar(2000)

CREATE TABLE #tmp_data_hold (
counter int identity(1, 1) NOT NULL,
field1 char(1) NULL)

INSERT INTO #tmp_data_hold
SELECT * FROM YourTable

SELECT @max_nbr_cols = COUNT(*) FROM YourTable

SET @counter = 1
SET @sql = 'CREATE TABLE #tmp_pivot_table ('
WHILE @counter <= @max_nbr_cols
BEGIN
SET @sql = @sql + ' col' + CONVERT(varchar, @counter) + ' varchar(10) NULL,'
SET @counter = @counter +1
END

SET @sql = STUFF(@sql, LEN(@sql), 1, ')')

EXEC(@sql)


SET @counter = 1
SET @sql = 'INSERT INTO #tmp_pivot_table SELECT '
WHILE @counter <= @max_nbr_cols
BEGIN
SET @sql = @sql + 'MAX(CASE counter WHEN ' + CONVERT(varchar, @counter) + ' THEN field1 ELSE '''' END) AS col' + CONVERT(varchar, @counter) + ', '
SET @counter = @counter +1
END

SET @sql = STUFF(@sql, LEN(@sql), 1, '')

SET @sql = @sql + ' FROM #tmp_data_hold'

EXEC(@sql)


--DROP TABLE #tmp_data_hold

SELECT * FROM #tmp_pivot_table


Basically, this code takes YourTable's data and inserts it into a temp table with an identity column. Then it dynamically creates another temp table whose number of columns is based on the number of records in YourTable. Then it dynamically creates a SELECT statement that flattens the table.

To better see what it does, comment out the "EXEC(@sql)" commands and substitute "PRINT @sql".


Edited: 01/20/2006 at 06:16 PM by nosepicker
    Reply     Quote     Top     Bottom    
 01/21/2006 08:09 AM
 User is offline  Print this message

Author Icon
SQLUSA

Posts: 2876
Joined: 05/17/2005

Check out this article: http://www.sqlusa.com/bestprac...osstabbyvendorbymonth/ .

Kalman Toth, BI Architect
http://www.sqlusa.com
The Best SQL Server 2005 Training in the World

    Reply     Quote     Top     Bottom    
 12/07/2007 07:51 AM
 User is offline  Print this message

Author Icon
mercybthomas74

Posts: 50
Joined: 12/07/2007

i tried to run this script and i get "Invalid object name '#tmp_pivot_table'."
Can you please guide me why I am getting this..
Thanks

-------------------------
sql_dev_jr
    Reply     Quote     Top     Bottom    
 12/12/2007 05:02 PM
 User is offline  Print this message

Author Icon
Pro Pete

Posts: 5093
Joined: 04/03/2002

The problem is that the temp table is being created by the first dynamic sql statement. This means it is not accessible to the second dynamic sql statement nor to the final SELECT statement.

In order for it to be available, both the creation and use must be in the same dynamic SQL statement. To achieve this, the line
SET @sql = 'INSERT INTO #tmp_pivot_table SELECT '
should be replaced by
SET @sql = @sql + 'INSERT INTO #tmp_pivot_table SELECT '
(strictly, the first "EXEC (@sql)" statement should also be commented out, but it will not cause any problem if it isn't.

The final select should also be moved into the end of the dynamic sql as:
SET @sql = @sql + ' FROM #tmp_data_hold
SELECT * FROM #tmp_pivot_table'

However, to be more useful to you, you probably need to be able to access the results from the code that generates and executes the dynamic sql. To achieve this you would need to use a temporary 'permanent' table. To do this, create the table in a database (could be tempdb) without the initial # symbol (e.g. CREATE TABLE tempdb.dbo.tmp_pivot_table) and rop it when you have finished with the data. If the code is to be executed concurrently by multiple users, then the table name will need to be modified to include some unique identification (e.g. the spid of the executing process).

Kalman's linked example solves a slightly different problem, but illustrates use of the PIVOT operator introduced in SQL2005.

-------------------------
Peter Kavanagh
MCDBA, MCSE
SQL Server Magazine Forum Pro

Edited: 12/12/2007 at 05:05 PM by Pro Pete
    Reply     Quote     Top     Bottom    
 12/13/2007 08:35 AM
 User is offline  View Users Profile  Print this message

Author Icon
gunneyk

Posts: 1156
Joined: 07/27/2007

Also if you are using SQL2005 then have a look at PIVOT & UNPIVOT specifically.

(Sorry I didn't see the other posts initially. I think Pete answered your question).

-------------------------
Andrew J. Kelly

Edited: 12/13/2007 at 08:42 AM by gunneyk
    Reply     Quote     Top     Bottom    
View topic in raw text format.
< REFRESH >

FuseTalk Enterprise Edition - © 1999-2010 FuseTalk Inc. All rights reserved.