UNION操作与同一个表

时间:2013-06-28 05:05:54

标签: sql oracle11g union-all

我有一个场景,我需要将单行中的数据作为多列进行查询,

表格格式如下,

SAMPLE_TABLE [ID,REF_TAB_A,REF_TAB_B,REF_TAB_C]

我需要在一列中使用REF_TAB_A,REF_TAB_B,REF_TAB_C值。我所做的是使用UNION ALL,如下所示,

SELECT REF_TAB_A FROM SAMPLE_TABLE 
UNION ALL
SELECT REF_TAB_B FROM SAMPLE_TABLE
UNION ALL
SELECT REF_TAB_C FROM SAMPLE_TABLE

有没有其他方法可以做到这一点?处理这种情况的最有效方法是什么?

(我正在使用oracle 11g)

提前致谢..:D

3 个答案:

答案 0 :(得分:2)

使用union all通常会导致对表格进行三次扫描。另一种方法有点麻烦,但应该只进行一次扫描:

SELECT (case when which = 'A' then REF_TAB_A
             when which = 'B' then REF_TAB_B
             when which = 'C' then REF_TAB_C
        end)
FROM SAMPLE_TABLE cross join
     (select 'A' as which from dual union all select 'B' from dual union all select 'C' from dual
     ) iter

答案 1 :(得分:0)

您可以为列添加别名:

SELECT REF_TAB_A tab FROM SAMPLE_TABLE 
UNION ALL
SELECT REF_TAB_B tab FROM SAMPLE_TABLE
UNION ALL
SELECT REF_TAB_C tab FROM SAMPLE_TABLE

然而,您真正需要做的是规范化您的数据库。每当您的列具有重复名称(如name1,name2,name3,namea,nameb和namec)时,它表示您需要另一个表以及它们之间的1-many关系。

CREATE TABLE tabs (
    tab_id NUMBER PRIMARY KEY,
    sample_table_id NUMBER,
    tab VARCHAR2(255),
    CONSTRAINT FK_sample_table
        FOREIGN KEY(sample_table_id)
        REFERENCES SAMPLE_TABLE(sample_table_id)
)

现在您的查询涉及一个简单的JOIN

SELECT
   tab
FROM tabs t
JOIN SAMPLE_TABLE st ON t.sample_table_id = st.sample_table_id
WHERE
    ...

答案 2 :(得分:0)

作为Gordon的CROSS JOIN技巧的替代方案,Oracle在SELECT语句中具有UNPIVOT clause专门针对这种情况。

假设这个表:

create table tmp_test ( a number, b number, c number );

insert all
 into tmp_test values (1,2,3)
 into tmp_test values (4,5,6)
select * from dual;

以下查询可以满足您的需求:

 select col
   from tmp_test
unpivot ( col for i in (a,b,c) );

       COL
----------
         1
         2
         3
         4
         5
         6

6 rows selected.

对于这个小例子,解释计划表明使用内置功能会更有效但是测试两个选项并看看哪个更好。