将同一个表中的子表转换为列

时间:2013-02-15 16:37:51

标签: sql database plsql pivot

我有一张这样的表:

+-------+-------+-------+-------+
|  ID   | City  | Param | Value |
+-------+-------+-------+-------+
| id1   | city1 | a     | value |
| id2   | city1 | b     | value |
| id3   | city1 | c     | value |
| id4   | city2 | a     | value |
| id5   | city2 | b     | value |
| id6   | city2 | c     | value |
| ...   | ...   | ...   | ...   |
| idN   | cityN | a     | value |
| idN+1 | cityN | b     | value |
| idN+2 | cityN | c     | value |
+-------+-------+-------+-------+

正如您所看到的,每个城市都有一个子表格,如:

+-------+-------+
| Param | Value |
+-------+-------+
| a     | value |
| b     | value |
| c     | value |
+-------+-------+

所以我想加入所有子表并得到一个这样的表:

+-------+-------+-------+-----+-------+
| Param | city1 | city2 | ... | cityN |
+-------+-------+-------+-----+-------+
| a     | value | value | ... | value |
| b     | value | value | ... | value |
| c     | value | value | ... | value |
+-------+-------+-------+-----+-------+

我有什么想法可以得到它吗?

提前谢谢!

注1:城市数量是可变的。

注2:解决方案可以是PL / SQL函数。

2 个答案:

答案 0 :(得分:1)

为了获得您想要的结果,您需要 pivot 数据。虽然您说plsql可能是一个选项,但您没有指定您正在使用的Oracle版本。从Oracle 11g开始,PIVOT功能可用。

如果您没有使用Oracle 119,那么您可以使用带有CASE表达式的聚合函数:

select param,
    max(case when city = 'city1' then value end) City1,
    max(case when city = 'city2' then value end) City2
from yourtable
group by param

请参阅SQL Fiddle with Demo

由于您声明您将拥有未知数量的city值,因此您需要创建此查询的动态sql版本。您可以创建类似于此的过程:

CREATE OR REPLACE procedure dynamic_pivot(p_cursor in out sys_refcursor)
as
    sql_query varchar2(1000) := 'select param ';

    begin
        for x in (select distinct city from yourtable order by 1)
        loop
            sql_query := sql_query ||
                ' , max(case when city = '''||x.city||''' then value else null end) as '||x.city;

                dbms_output.put_line(sql_query);
        end loop;

        sql_query := sql_query || ' from yourtable group by param order by param';
        dbms_output.put_line(sql_query);

        open p_cursor for sql_query;
    end;
/

然后,要获得结果,您可以使用以下内容(注意:我在TOAD中使用此):

variable x refcursor
exec dynamic_pivot(:x)
print x

您的查询结果将是:

| PARAM | CITY1 | CITY2 |
-------------------------
|     a | value | value |
|     b | value | value |
|     c | value | value |

答案 1 :(得分:0)

如果你有10G,你可以使用11G中的新pivotmodel子句。 检查文档。