UNION operation with the same table



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

表格格式如下,

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

有别的办法吗??处理这种情况最有效的方法是什么??

(我使用的是oracle11g)

提前感谢..:D

使用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

您可以将列别名为:

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位关系。

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
    ...

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

假设此表:

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.

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

相关内容

  • 没有找到相关文章

最新更新