views:

4211

answers:

4

I am working with a table where there are multiple rows that I need pivoted into columns. So the pivot is the perfect solution for this, and works well when all I need is one field. I am needing to return several fields based upon the pivot. Here is the pseudo code with specifics stripped out:

SELECT 
  field1,
  [1], [2], [3], [4]
FROM
  (
  SELECT 
    field1, 
    field2, 
    (ROW_NUMBER() OVER(PARTITION BY field1 ORDER BY field2)) RowID
  FROM tblname
  ) AS SourceTable
PIVOT
  (
  MAX(field2)
  FOR RowID IN ([1], [2], [3], [4])
  ) AS PivotTable;

The above syntax works brilliantly, but what do I do when I need to get additional information found in field3, field4....?

+1  A: 

I am unsure if you are using MS SQL Server, but if you are... You may want to take a look at the CROSS APPLY functionality of the engine. Basically it will allow you to apply the results of a table-valued UDF to a result set. This would require you to put your pivot query into a table-valued result set.

http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/sql-server-cross-apply.aspx

Jon Erickson
-1 Can't see relation with question
Andomar
RolandTumble
+3  A: 

Rewrite using MAX(CASE...) and GROUP BY:

select 
  field1
, [1] = max(case when RowID = 1 then field2 end)
, [2] = max(case when RowID = 2 then field2 end)
, [3] = max(case when RowID = 3 then field2 end)
, [4] = max(case when RowID = 4 then field2 end)
from (
  select 
    field1
  , field2
  , RowID = row_number() over (partition by field1 order by field2)
  from tblname
  ) SourceTable
group by 
  field1

From there you can add in field3, field4, etc.

Peter
What I ended up doing was using CASe statements in a CTE to populate this derived table, which I joined with additional criteria.Here is the CTE:
websch01ar
With cteSec as ( SELECT vSec.ID, --Secretary 1 ------------------------- MAX( CASE vSec.RowID WHEN 1 THEN vSec.field1 ELSE '' END ) [SEC_OfficePhone1], MAX( CASE vSec.RowID WHEN 1 THEN vSec.field2 ELSE '' END ) [SEC_OfficeFax1], FROM ( --THIS WILL BE THE INNER QUERY (it assigns rows to secretaries) SELECT TOP 100 PERCENT field1, field2, ID (ROW_NUMBER() OVER(PARTITION BY vs.ID ORDER BY vs.ID2)) RowID FROM tblname vs ORDER BY vs.ID, ID2 ) vSec GROUP BY vSec.ID )
websch01ar
So through this method I have hardcoded the number of columns I am expecting. I generally would prefer to do this dynamically, as its bound to change. But as a company, we are focusing on overhead reduction, so I do not see the need for more than four secretaries per boss...I am giving you the credit because your post led me down the road to writing the 20 case statements. This works like a charm with a sub-second response.
websch01ar
Glad to be of help. A text editor with column mode/rectangular edit really helps with writing the repetitive CASE statements. UltraEdit and Emacs come to mind.For a dynamic number of columns, you would need to use dynamic SQL. Here's the best place to read about that: http://www.sommarskog.se/dynamic_sql.htmlAlso, I'm not sure the TOP 100 PERCENT ... ORDER BY trick still works reliably after SQL2K. The ROW_NUMBER() function will force the results into that order anyhow.
Peter
A: 

I have requirement even if more complicate than multiple column pivot. The case is: 1) there are 3 fields need to be moved from rows into columns. 2) for solve 3 fields issue, instead of using pivot I have to use Case When... However it doesn't work either, 3) for using case when, it needs group by. However there are multiple rows in each columns segment(after been pivoted), and the different value of pivoted columns should fits into same row at the end.

Thank you

A: 

wrap your sql statement with something like:

select a.segment, sum(field2), sum(field3) from (original select with case arguments) a group by a.segment

It should collapse your results into one row, grouped on field1.

Mark Grizzle