我们如何编写一个plsql代码,将表A的值转换为表B.
表A
rec_id || col1 || col2 || col3
2 val1 val2 val3
3 val4 val5 val6
表B中所需的输出
表B
rec_id || type || value
2 col1 val1
2 col2 val2
2 col3 val3
3 col4 val5
3 col5 val5
3 col6 val6
仅当val1或val2或val3不为空时。如果任何值为null,那么表B中不应该有rec。例如,如果val2为null,则
rec_id || type || value
2 col1 val1
2 col3 val3
答案 0 :(得分:1)
在Oracle 11.1及更高版本中,您可以使用AdditionalDataId
。我添加了一些测试数据来显示UNPIVOT
的处理方法。 (请记住,在Oracle中,空字符串NULL
与''
相同。)
NULL
答案 1 :(得分:0)
您可以使用union all
(以及其他方法)执行此操作:
select rec_id, 'col1' as type, col1 as value from t where col1 is not null union all
select rec_id, 'col2' as type, col2 as value from t where col2 is not null union all
select rec_id, 'col3' as type, col3 as value from t where col3 is not null;
您似乎想要消除任何出现NULL
的行和列:
select rec_id, type, value
from (select t.*,
(case when count(*) over (partition by type) = count(value) over (partition by type)
then 1 else 0
end) as no_null_type,
(case when count(*) over (partition by recid) = count(value) over (partition by recid)
then 1 else 0
end) as no_null_recid
from (select rec_id, 'col1' as type, col1 as value from t union all
select rec_id, 'col2' as type, col2 as value from t union all
select rec_id, 'col3' as type, col3 as value from t
) t
) t
where no_null_type = 1 and no_null_recid = 1;
在Oracle 12c中,您可以使用横向连接:
select t.rec_id, x.type, x.value
from t cross apply
(select 'col1' as type, col1 as value from dual union all
select 'col2' as type, col2 as value from dual union all
select 'col3' as type, col3 as value from dual
) x
where value is not null;
这样做的好处是只扫描一次表。您可以应用类似的逻辑来删除NULL
。
答案 2 :(得分:0)
我知道您显示的表名不是您想要运行查询的实际表,它可能有超过3列。
所以我想出了一个PLSQL程序(如果你想在sql中,那么其他答案会帮助你)
DECLARE
SQLSELECT VARCHAR2(1000);
SQLINSERT VARCHAR2(1000);
TYPE TCur IS REF CURSOR;
cur TCur;
TYPE TRec IS RECORD (ID INT,
COL_VAL VARCHAR2(20));
v_rec TRec;
BEGIN
FOR rec IN
(SELECT column_name
FROM all_tab_columns
WHERE table_name = 'TABLEA')
LOOP
IF (rec.column_name <> 'REC_ID') THEN
SQLSELECT:= 'SELECT ID,'||rec.column_name||' column_name FROM TABLEA
where '||rec.column_name||' is not null';
OPEN cur FOR SQLSELECT;
LOOP
FETCH cur INTO v_rec;
EXIT WHEN cur%notfound;
-- DBMS_OUTPUT.PUT_LINE(v_rec.ID||' '||v_rec.COL_VAL||' '||rec.column_name);
SQLINSERT:= 'INSERT INTO TABLEB VALUES(:1, :2, :3)';
--DBMS_OUTPUT.PUT_LINE(SQLINSERT);
EXECUTE IMMEDIATE SQLINSERT USING v_rec.ID,v_rec.COL_VAL,rec.column_name;
END LOOP;
END IF;
END LOOP;
END;
在这里,您必须根据您的表格ID更改TABLEA
和REC_ID
,您必须在运行代码之前创建目标表,并将TABLEB
替换为您的目的地表名称。它还将涵盖无效条件。在调试代码时,注释语句很有用