Sql 以Oracle 10g为中心
我正在使用oracle 10g。 我有一张临时桌 TEMP具有以下结构:-Sql 以Oracle 10g为中心,sql,oracle,oracle10g,pivot,Sql,Oracle,Oracle10g,Pivot,我正在使用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 0 2 0 2
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 0
2 0 21 1
3 45 0 0
“用户”列将显示所有用户,T1、T2列将显示类型总数 以下是创建表的代码:
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 Fiddle链接中检查它请检查查询:
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 ;
要选择数据,请使用语句OPEN CUR\U TURN\U TIME进行V\U查询;代替DBMS_OUTPUT.PUT_LINEV_QUERY;,其中CUR\u TURN\u TIME是程序包中声明的游标。在Oracle 10g中,没有PIVOT函数,但您可以使用一个带有CASE的聚合来复制它: 看 如果您有Oracle 11g+,则可以使用PIVOT功能:
select *
from temp
pivot
(
sum(cnt)
for tp in ('T1', 'T2', 'T3')
) piv
看
如果要转换的值数目未知,则可以创建一个过程来生成此值的动态版本:
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 |
编辑:根据您的评论,如果您想要一个总计字段,最简单的方法是将查询放置在另一个类似以下内容的选择中:
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;
请参见您需要给出一个更清晰的示例,说明示例表的结果。@JoachimIsaksson请检查编辑问题中的示例输出没有静态sql解决方案,除非您的T1。。总氮量是有限的和已知的。否则,动态sql和ref游标是您的选项+1。对于未来的用户,我需要在USER和T1之间有一列来显示类型的总数,如何通过查询来完成。输出应该是这样的:-USR | total | T1 | T2 | T3 |------total列将显示T1,T2,T3@little您最好的选择是将您的查询放在另一个select中,与此演示类似,我还需要一个帮助。我必须用标题显示所有行的总计。总计将与标题一起添加,其中总计是该列的总和。就像用户| total|u total | T1|u total | T2|total |那样,您将在select语句中使用列别名。所以选择usr作为用户,等等。但是如果你有其他问题,你应该发布一个新问题。我已经发布了一个新问题,
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;