我的表格中有这一行mtinre:
INREPRCO INRESELO INRECAPI INRECFRA INRECAPO
---------- ---------- ---------- ---------- ----------
32.42 1.87 1 5
我构建了一个查询,将此行转换为每列5个不同的行。
SELECT CASE pivot
WHEN 1 THEN 'VAPRS'
WHEN 2 THEN 'VAFRC'
WHEN 3 THEN 'VACTA'
WHEN 4 THEN 'VIMSL'
WHEN 5 THEN 'VINEM'
END
component,
CASE pivot
WHEN 1 THEN inreprco
WHEN 2 THEN inrecfra
WHEN 3 THEN inrecapo
WHEN 4 THEN inreselo
WHEN 5 THEN inreinem
ELSE NULL
END
VALUE,
CASE pivot
WHEN 4
THEN
(NVL (inreprco, 0) + NVL (inrecfra, 0) + NVL (inrecapo, 0))
WHEN 5
THEN
(NVL (inreprco, 0) + NVL (inrecfra, 0) + NVL (inrecapo, 0))
ELSE
NULL
END
AS base
FROM mtinre,
( SELECT ROWNUM pivot
FROM DUAL
CONNECT BY LEVEL <= 5)
输出结果为:
COMPONENT VALUE BASE
--------- ---------- ----------
VAPRS 32.42
VAFRC
VACTA 5
VIMSL 1.87 37.42
VINEM .94 37.42
但是这5个字段(INREPRCO,INRESELO,INRECAPI,INRECFRA,INRECAPO)可以具有零或零(0)值。所以我只需要选择那些有价值的东西。 在最后一个例子中,只显示我:
COMPONENT VALUE BASE
--------- ---------- ----------
VAPRS 32.42
VACTA 5
VIMSL 1.87 37.42
VINEM .94 37.42
我试图把一些条件放在哪里,但是按层次连接语句总是让我产生5行。
所以,我改变了我的查询并做了这个:
SELECT *
FROM (SELECT CASE pivot
WHEN 1 THEN 'VAPRS'
WHEN 2 THEN 'VAFRC'
WHEN 3 THEN 'VACTA'
WHEN 4 THEN 'VIMSL'
WHEN 5 THEN 'VINEM'
END
component,
CASE pivot
WHEN 1 THEN inreprco
WHEN 2 THEN inrecfra
WHEN 3 THEN inrecapo
WHEN 4 THEN inreselo
WHEN 5 THEN inreinem
ELSE NULL
END
VALUE,
CASE pivot
WHEN 4
THEN
( NVL (inreprco, 0)
+ NVL (inrecfra, 0)
+ NVL (inrecapo, 0))
WHEN 5
THEN
( NVL (inreprco, 0)
+ NVL (inrecfra, 0)
+ NVL (inrecapo, 0))
ELSE
NULL
END
AS base
FROM mtinre,
( SELECT ROWNUM pivot
FROM DUAL
CONNECT BY LEVEL <= 5))
WHERE VALUE IS NOT NULL
它有效,但有没有其他方法可以不使用子选择语句? 有什么建议吗?
由于 菲利普
答案 0 :(得分:3)
使用UNPIVOT和一个小技巧可以完成这项工作。几乎所有表都有一个id列(主键或唯一键)。假设该表具有id_col作为id列,则此查询将执行作业
SQL> WITH table_(id_col, inreprco,inreselo,inrecapi,inrecfra,inrecapo) AS
2 (SELECT 1, 32.42,1.87,0.94,NULL,5 FROM dual UNION ALL
3 SELECT 2, 33.43,2.87,0.87,12,9 FROM dual ),
4 ---------
5 -- End of data preparation
6 ---------
7 table2_ AS (SELECT id_col, component, VALUE
8 FROM table_
9 UNPIVOT (VALUE FOR component IN (inreprco AS 'VAPRS', inrecfra AS 'VAFRC', inrecapo AS 'VACTA', inreselo AS 'VIMSL', inrecapi AS 'VINEM')))
10 select a.id_col,
11 a.COMPONENT,
12 a.VALUE,
13 CASE WHEN a.component IN ('VIMSL', 'VINEM') THEN nvl(b.inreprco, 0) + nvl(b.inrecfra, 0) + NVL(b.inrecapo, 0) ELSE NULL END AS base
14 FROM table2_ a
15 INNER JOIN table_ b
16 ON b.id_col = a.id_col;
ID_COL COMPONENT VALUE BASE
---------- --------- ---------- ----------
1 VAPRS 32.42
1 VACTA 5
1 VIMSL 1.87 37.42
1 VINEM 0.94 37.42
2 VAPRS 33.43
2 VAFRC 12
2 VACTA 9
2 VIMSL 2.87 54.43
2 VINEM 0.87 54.43
9 rows selected
但是如果没有Id列,那么将连接修改为交叉连接将会执行,但如果表中只有一行,则会返回正确的结果。
SQL> WITH table_(inreprco,inreselo,inrecapi,inrecfra,inrecapo) AS
2 (SELECT 32.42,1.87,0.94,NULL,5 FROM dual),
3 ---------
4 -- End of data preparation
5 ---------
6 table2_ AS (SELECT component, VALUE
7 FROM table_
8 UNPIVOT (VALUE FOR component IN (inreprco AS 'VAPRS', inrecfra AS 'VAFRC', inrecapo AS 'VACTA', inreselo AS 'VIMSL', inrecapi AS 'VINEM')))
9 select a.COMPONENT,
10 a.VALUE,
11 CASE WHEN a.component IN ('VIMSL', 'VINEM') THEN nvl(b.inreprco, 0) + nvl(b.inrecfra, 0) + NVL(b.inrecapo, 0) ELSE NULL END AS base
12 FROM table2_ a
13 CROSS JOIN table_ b
14 /
COMPONENT VALUE BASE
--------- ---------- ----------
VAPRS 32.42
VACTA 5
VIMSL 1.87 37.42
VINEM 0.94 37.42
或等待有其他方法的人;)