views:

2193

answers:

6

I have a table that looks like this:

A 1 
A 2 
B 1 
B 2

And I want to produce a result set that looks like this:

A 1 2 
B 1 2

Is there a SQL statement that will do this? I am using Oracle.

Related questions:

+2  A: 

See similar question advice-using-pivot-table-in-oracle

Tony Andrews
+1  A: 

User defined aggregate functions: http://www.adp-gmbh.ch/ora/sql/user_def_agg.html

Just copy/paste and use it. Works on 9i.

jva
+3  A: 

It depends on the version of Oracle you're using. If it supports the wm_concat() function, then you can simply do something like this:

SELECT field1, wm_concat(field2) FROM YourTable GROUP BY field2;

wm_concat() basically works just like group_concat() in MySQL. It may not be documented, so fire up ye olde sqlplus and see if it's there.

If it isn't there, then you'll want to implement something equivalent yourself. You can find some instructions on how to do this in the string aggregation page at oracle-base.com.

John Hyland
+2  A: 

Try something like :

SELECT
    field1,
    RTRIM(REPLACE(REPLACE(XMLAgg(XMLElement("x", field2) ORDER BY field2), '<x>'), '</x>', ' ')) AS field2s
  FROM yourTable
  GROUP BY field1

Freely inspired by an answer found in this Oracle forum.

EDIT: this solution proved very resources intensive with requests involving something like 105 rows. I ended up replacing this by custom aggregate functions as suggested by John.

Mac
+1  A: 

In Oracle 10g+:

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        MODEL
        PARTITION BY
                (grouper)
        DIMENSION BY
                (ROW_NUMBER() OVER (PARTITION BY grouper ORDER BY id) AS rn)
        MEASURES
                (val, val AS group_concat, 0 AS mark)
        RULES SEQUENTIAL ORDER (
                group_concat[rn > 1] ORDER BY rn = group_concat[CV() - 1] || ', ' || val[CV()],
                mark[ANY] ORDER BY rn = PRESENTV(mark[CV() + 1], 0, 1)
                )
        )
WHERE   mark = 1
ORDER BY
        grouper

See this article in my blog for explanations:

Quassnoi
You are totally dependent on mytable being sorted by rn. If it is not sorted you'll get an "ORA-32637: Self cyclic rule in sequential order MODEL". So this variant is buggy. You may want to read another model clause variant on my blog: http://rwijk.blogspot.com/2008/05/string-aggregation-with-model-clause.html
Rob van Wijk
@Rob: `rn` here is just an alias for `ROW_NUMBER()`. I copied it from my article (which used a `CTE` as a rowsource) but didn't put it into the table. Thanks for noticing.
Quassnoi
Yes, I know. But if, for instance, you used another analytic function with a different order by, and that accompanying WINDOW SORT operation is executed last, you get the aforementioned error. So you still have to use ordered rule evaluation to make this idea work.
Rob van Wijk
@Rob: right again, updated, checked with `6 - ROW_NUMBER() OVER (PARTITION BY grouper ORDER BY rno) AS rn`. Thanks.
Quassnoi
A: 

Mac, you've got a magical solution!!!

Omri
Thank you, but beware of the poor performance of my solution (I edited my answer)...
Mac