views:

787

answers:

2

Hi All,

my question is, with some background:

I have to generate some sql queries based on the table metadata (column format), and the result is something like:

TABLENAME1|COL1
TABLENAME1|COL2
TABLENAME2|COL1
TABLENAME2|COL2
TABLENAME2|COL3
TABLENAME3|COL1
TABLENAME4|COL1
TABLENAME4|COL2
... /*some other 1800 rows */

(Yeah, it's ordered.) What I need is to transpose this data, based on the first column, so the expected output would be:

TABLENAME1|COL1|COL2|NULL
TABLENAME2|COL1|COL2|COL3
TABLENAME3|COL1|NULL|NULL
TABLENAME4|COL1|COL2|NULL
/* less then 1800 rows ;-) */

Is it possible using Oracle SQL?

Thanks in advance!

+1  A: 

The keyword that you're looking for is pivot. Here's an example of its use. The syntax appears generally the same as MSSQL, and since I don't know the url for Oracle's documentation I'll toss up the MSDN link and hope that someone that knows more about Oracle's page layout than me will edit it to point to their documentation.

EDIT: Oracle documentation, search for pivot enough times and you'll get to the details.

Donnie
Pivot was one of the coolest additions to hit SQL ever. Want to denormalize your query results without hard-coding columns or writing nasty cursors? Pivot!
Dathan
But does it works when I don't now how many columns will appear in the result table?
Zsolt Botykai
There is no way in SQL to do a dynamic number of columns short of dynamically generating the SQL in your front end before running it. If you know the maximum number of columns that could appear in the result set then it should work ok as long as you don't mind a bunch of nulls.
Donnie
Thanks I'm looking into it, or I will export the result, and create an AWK wrapper, to generate my queries.
Zsolt Botykai
The Oracle doc mentions the pivot operator in the description of the select statement. There are links leading into the data warehouse guide from there. http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_10002.htm#i2065646
Juergen Hartelt
+1  A: 

If you want to generate the query for each call or use a hardcoded max-column-count, then you can do something like that:

WITH tab AS
(
  SELECT table_name, column_name FROM user_tab_cols WHERE column_id <= 4
) -- user_tab_cols used to provide test data, use your table instead
SELECT MAX(c1) c1,
       MAX(c2) c2,
       MAX(c3) c3,
       MAX(c4) c4
  FROM (SELECT table_name,
               DECODE( column_id, 1, column_name ) c1,
               DECODE( column_id, 2, column_name ) c2,
               DECODE( column_id, 3, column_name ) c3,
               DECODE( column_id, 4, column_name ) c4
          FROM ( SELECT table_name,
                        column_name,
                        ROW_NUMBER() OVER ( PARTITION BY table_name ORDER BY column_name ) column_id
                   FROM tab
               )
       )
 GROUP BY table_name
 ORDER BY table_name


If it is sufficient to get it in that form

TABLENAME1|COL1,COL2
TABLENAME2|COL1,COL2,COL3

have a look at Tom Kyte's stragg.

Peter Lang
Thanks I will give it a try!
Zsolt Botykai
Tom Kyte's stragg had helped.
Zsolt Botykai