0

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

表格格式如下,

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)

先谢谢了

4

3 回答 3

2

Using union all generally results in three scans of the table. An alternative approach is a little messier but should have just one scan:

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
于 2013-06-28T05:12:31.110 回答
0

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

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

于 2013-06-28T07:47:01.407 回答
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)时,这表明您需要另一个表以及它们之间的一对多关系。

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
    ...
于 2013-06-28T05:22:21.170 回答