all groups > sql server programming > june 2007 >
You're in the

sql server programming

group:

Turning data into columns


Re: Turning data into columns Erland Sommarskog
6/30/2007 9:38:44 PM
sql server programming: Debbie Croft (debbie.croft@nospamforme.com) writes:
[quoted text, click to view]

A SELECT query produces a table. A table has column with known names, and
therefore also the number of column must be known. Thus, if there can be
any number of years in the table, you cannot write this in a single SELECT.
If you can assume that there are at most, say, three years, you can write
it as a query, but you need to accept that the year cannot be indicated
in the column header, but that will have to be a separate column.

Here is a query for SQL 2005 that produces this:

CREATE TABLE somevalues (Company varchar(12) NOT NULL,
year char(4) NOT NULL,
value int NOT NULL,
PRIMARY KEY (Company, year))
go
INSERT somevalues (Company, year, value)
SELECT 'CompanyA', '1998', 378 UNION ALL
SELECT 'CompanyB', '1998', 45 UNION ALL
SELECT 'CompanyC', '1998', 245 UNION ALL
SELECT 'CompanyA', '1999', 754 UNION ALL
SELECT 'CompanyB', '1999', 298 UNION ALL
SELECT 'CompanyC', '1999', 7 UNION ALL
SELECT 'CompanyA', '2000', 347 UNION ALL
SELECT 'CompanyB', '2000', 32 UNION ALL
SELECT 'CompanyC', '2000', 186
go
SELECT Company,
Year1 = MIN(CASE y.rn WHEN 1 THEN s.year END),
Value_year1 = MIN(CASE y.rn WHEN 1 THEN s.value END),
Year2 = MIN(CASE y.rn WHEN 2 THEN s.year END),
Value_year3 = MIN(CASE y.rn WHEN 2 THEN s.value END),
Year3 = MIN(CASE y.rn WHEN 3 THEN s.year END),
Value_year2 = MIN(CASE y.rn WHEN 3 THEN s.value END)
FROM somevalues s
JOIN (SELECT DISTINCT year,
rn = dense_rank() OVER (ORDER BY year)
FROM somevalues) AS y ON s.year = y.year
GROUP BY Company
go
DROP TABLE somevalues


If you absolute must have the column names dynamic and/or have a
dynamic set of columns, you must build the query dynamically and
execute it with sp_executesql. This is quite steep increase in
complexity.



--
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
Turning data into columns Debbie Croft
6/30/2007 9:46:15 PM
I have a database that has a table similar to the following:

ID Company Year Value
----------------------
1 CompanyA 1998 378
2 CompanyB 1998 45
3 CompanyC 1998 245
4 CompanyA 1999 754
5 CompanyB 1999 298
6 CompanyC 1999 7
7 CompanyA 2000 347
8 CompanyB 2000 32
9 CompanyC 2000 186

I'd like to output this as:

Company 1998 1999 2000
-----------------------
CompanyA 378 754 347
CompanyB 45 298 32
CompanyC 245 7 186

The problem is that I'd don't know before hand what years are in the
database - they change as new data is added.

What's the best way to write a query that performs this transformation? Can
it be done using set logic (i.e. without procedural code)?

Re: Turning data into columns Greg Linwood
7/1/2007 12:00:00 AM
If you need a good option for doing dynamic crosstab, Geckoware's crosstab
builder does a great job of dynamically building crosstab queries.
http://www.geckoware.com.au/

This tool is much more efficient than temp tables / table variables as its
an in-proc dll (xp_) which works in memory rather than on disk (as temp
objects do).

Regards,
Greg Linwood
SQL Server MVP
http://blogs.sqlserver.org.au/blogs/greg_linwood
Benchmark your query performance
http://www.SQLBenchmarkPro.com

[quoted text, click to view]

Re: Turning data into columns Erland Sommarskog
7/1/2007 12:00:00 AM
Greg Linwood (g_linwood@hotmail.com) writes:
[quoted text, click to view]

XPs? Isn't time to make a CLR solution for SQL2005?

--
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
Re: Turning data into columns Greg Linwood
7/1/2007 12:00:00 AM
Not necessarily - arrays are slower in CLR than in xp_'s so doing this would
mean a performance trade off.

Regards,
Greg Linwood
SQL Server MVP
http://blogs.sqlserver.org.au/blogs/greg_linwood
Benchmark your query performance
http://www.SQLBenchmarkPro.com

[quoted text, click to view]

Re: Turning data into columns Erland Sommarskog
7/1/2007 12:00:00 AM
Greg Linwood (g_linwood@hotmail.com) writes:
[quoted text, click to view]

On the other hand, there is a context switch to invoke an XP which is
costly.

Then again, I can't really see that this matters. To run a dynamic pivot,
you need to:
1) Get the distinct values of the column you want to pivot.
2) Somehow traverse that data to build a SELECT statement.
3) Run that SELECT statement.

Reasonably, it most cases the cost will be for the first and last steps,
and whether you make the second step in T-SQL, C# or C++ may not give
any measurable difference in performance. However, particularly C# is a
more friendly environment to build the SQL string in.

Or does this XP read all data with a regular query, and then restructure
the result set, before it is returned to the client. In this case, there
may be some advantage with native code or managed code. But would it not
be even better to do this reshaping client-side? An XP or a CLR procedure
that allocates large amounts of memory for its own purposes is not very
friendly to SQL Server.

--
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
Re: Turning data into columns Greg Linwood
7/1/2007 12:00:00 AM
Context switches are only costly if they happen at high reptition.

Running the second step in T-SQL usually means hammering the disk with IO
which puts performance problems into a higher dimension.

There is a big difference in array management between C# & C++.

Regards,
Greg Linwood
SQL Server MVP
http://blogs.sqlserver.org.au/blogs/greg_linwood
Benchmark your query performance
http://www.SQLBenchmarkPro.com

[quoted text, click to view]

Re: Turning data into columns Steve Dassin
7/1/2007 2:14:55 PM
Performance is king. But what few seem to be aware of is what is
left in its wake. And what could possibly be good about something
slow?

www.beyondsql.blogspot.com

[quoted text, click to view]

Re: Turning data into columns Erland Sommarskog
7/1/2007 3:12:05 PM
Greg Linwood (g_linwood@hotmail.com) writes:
[quoted text, click to view]

Hammering the disk with I/O? Come on! You have a temp table with, say, 30
rows in it. It will be written to disk when the data is inserted, and then
read from cache.

[quoted text, click to view]

Maybe. But it is not going be significant to handle 30 values. Or
for that matter 4096 which is the most you will be able to cram into
the query anyway.


--
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
AddThis Social Bookmark Button