2012-11-16 162 views
1

我正在使用oracle 10g。 我有一个临时表TEMP。Oracle 10g枢轴

TEMP具有以下结构: -

USER COUNT TYPE 
---- ----- ---- 
    1 10 T1 
    2 21 T2 
    3 45 T1 
    1  7 T1 
    2  1 T3 

我需要一个查询,它会显示所有类型都有列名和类型可以有任何价值一样T1, T2,..Tn和结果会是这样的: -

USER T1 T2 T3 
---- -- -- -- 
    1 17 0 1 
    2 0 21 1 
    3 45 0 0 

和用户列将显示所有用户和T1, T2列将显示类型的总数。

+0

不知道如何做到这一点 – F11

+0

你需要给出一个更明显的例子你的结果应与样本表一致。 –

+0

@JoachimIsaksson请查看编辑问题 – F11

回答

5

在Oracle 10g中,没有PIVOT功能,但你可以使用聚合与CASE复制它:

select usr, 
    sum(case when tp ='T1' then cnt else 0 end) T1, 
    sum(case when tp ='T2' then cnt else 0 end) T2, 
    sum(case when tp ='T3' then cnt else 0 end) T3 
from temp 
group by usr; 

SQL Fiddle with Demo

如果你的Oracle 11g +,那么你可以使用PIVOT功能:

select * 
from temp 
pivot 
(
    sum(cnt) 
    for tp in ('T1', 'T2', 'T3') 
) piv 

SQL Fiddle with Demo

如果你有一个未知的数值进行改造的,那么你可以创建一个过程来产生这个动态的版本:

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

    begin 
     for x in (select distinct tp from temp order by 1) 
     loop 
      sql_query := sql_query || 
       ' , sum(case when tp = '''||x.tp||''' then cnt else 0 end) as '||x.tp; 

       dbms_output.put_line(sql_query); 
     end loop; 

     sql_query := sql_query || ' from temp group by usr'; 

     open p_cursor for sql_query; 
    end; 
/

然后执行该代码:

variable x refcursor 
exec dynamic_pivot(:x) 
print x 

结果所有版本是相同的:

| USR | T1 | T2 | T3 | 
---------------------- 
| 1 | 17 | 0 | 0 | 
| 2 | 0 | 21 | 1 | 
| 3 | 45 | 0 | 0 | 

编辑:基于您的评论,如果你想有一个Total˚F ield,最简单的方法是将查询放置另一个SELECT类似这样的内部:

select usr, 
    T1 + T2 + T3 as Total, 
    T1, 
    T2, 
    T3 
from 
(
    select usr, 
    sum(case when tp ='T1' then cnt else 0 end) T1, 
    sum(case when tp ='T2' then cnt else 0 end) T2, 
    sum(case when tp ='T3' then cnt else 0 end) T3 
    from temp 
    group by usr 
) src; 

SQL Fiddle with Demo

+0

,我需要在USER和T1之间的一列显示类型的总数,如何通过查询来完成。输出应该是: - | USR |合计| T1 | T2 | T3 | ----------------------总列将显示T1,T2,T3的总和 – F11

+0

@您最好的选择是将您的查询置于另一个选择内,类似到这个演示 - http://www.sqlfiddle.com/#!4/a42bb/5 – Taryn

+0

,我需要一个更多的帮助。我必须显示所有行的总数与header.Total将被添加与头在哪里总和是sum像User | Total_Total | T1_Total | T2_Total | – F11

2

下面是创建表的代码:

CREATE TABLE TBL_TEMP 
(
    USR NUMBER 
    ,CNT NUMBER 
    ,TP VARCHAR2 (10) 
); 

INSERT INTO TBL_TEMP VALUES (1,10,'T1'); 
INSERT INTO TBL_TEMP VALUES (2,21,'T2'); 
INSERT INTO TBL_TEMP VALUES (3,45,'T1'); 
INSERT INTO TBL_TEMP VALUES (1,7,'T1'); 
INSERT INTO TBL_TEMP VALUES (2,1,'T3'); 

而且,这里是你的请求代码:

SELECT T1.USR 
     ,SUM (T1) T1 
     ,SUM (T2) T2 
     ,SUM (T3) T3 
    FROM (SELECT DISTINCT USR FROM TBL_TEMP) T1 
     ,(SELECT T2.USR 
       ,DECODE (T2.TP, 'T1', T2.CNT, 0) T1 
       ,DECODE (T2.TP, 'T2', T2.CNT, 0) T2 
       ,DECODE (T2.TP, 'T3', T2.CNT, 0) T3 
      FROM TBL_TEMP T2) T2 
    WHERE T1.USR = T2.USR 
GROUP BY T1.USR; 

而且,结果是你想要的。

在SQL小提琴菱格纹它here

+0

+1。对于未来的用户,[Oracle 11g引入了透视功能](http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10002.htm#CHDCEJJE) – danihp

0

请检查查询:

SET SERVEROUTPUT ON; 
DECLARE 
CURSOR V_CUR IS 
SELECT DISTINCT "TYPE" FROM temp_tbl; 

V_QUERY CLOB; 
V_COLUMNHEADING CLOB; 
V_ROW V_CUR%ROWTYPE; 
BEGIN 
    OPEN V_CUR; 
    LOOP 
    FETCH V_CUR INTO V_ROW; 
    EXIT WHEN V_CUR%NOTFOUND; 
    V_COLUMNHEADING:=CONCAT(V_COLUMNHEADING,''''||V_ROW."TYPE"||''' AS "'||V_ROW."TYPE"||'",'); 
    END LOOP; 

    IF NVL(V_COLUMNHEADING,' ') <> ' ' THEN 
     V_COLUMNHEADING := SUBSTR(V_COLUMNHEADING,0,LENGTH(V_COLUMNHEADING)-1); 
    END IF; 

    V_QUERY := CONCAT(V_QUERY,'select * from (select * from temp_tbl)a pivot (sum("COUNT")for "TYPE" in ('||V_COLUMNHEADING||'))b;'); 
    DBMS_OUTPUT.PUT_LINE(V_QUERY); 
END ; 

要到位DBMS_OUTPUT.PUT_LINE(V_QUERY);,其中CUR_TURN_TIME是在包中声明的光标选择数据,使用的语句OPEN CUR_TURN_TIME FOR V_QUERY;