2013-05-02 36 views
0

我有一张表,其中多个帐号与不同的ID(DR_NAME)相关联。每个帐户最多只能有0个帐户,多达16个。我相信UNPIVOT可以工作,但我使用的是Oracle 10g,但不支持此功能。如何在Oracle 10g中将多个列值作为新行返回?

DR_NAME ACCT1 ACCT2 ACCT3 ACC4 
====================================== 
SMITH  1234 
JONES  5678 2541 2547 
MARK  NULL  
WARD  8754 6547 

我想显示每个名称的新行,每行只有1个账号

DR_NAME ACCT 
============== 
SMITH  1234 
JONES  5678 
JONES  2541 
JONES  2547 
MARK  NULL 
WARD  8754 
WARD  6547 
+0

多少数据行做你需要做的这因为在单个查询中,您是否需要选择该数据或将其插入到表中? – 2013-05-02 14:09:09

+0

@DavidAldridge大约1500行的初始数据,据我估计,当每个DR_NAME仅与1个ACCT配对时,可能会产生大约6000行。它需要被插入到一个表中 – user2249376 2013-05-02 14:26:28

回答

1

Oracle 10g中不具有UNPIVOT功能,但你可以使用一个UNION ALL查询UNPIVOT列成行:

select t1.DR_NAME, d.Acct 
from yourtable t1 
left join 
(
    select DR_NAME, ACCT1 as Acct 
    from yourtable 
    where acct1 is not null 
    union all 
    select DR_NAME, ACCT2 as Acct 
    from yourtable 
    where acct2 is not null 
    union all 
    select DR_NAME, ACCT3 as Acct 
    from yourtable 
    where acct3 is not null 
    union all 
    select DR_NAME, ACCT4 as Acct 
    from yourtable 
    where acct4 is not null 
) d 
    on t1.DR_NAME = d.DR_NAME; 

参见SQL Fiddle with Demo

此查询使用UNION ALL将列转换为行。我包含一个where子句以删除任何null值,否则您将针对acct值为空的每个帐户获取多行。不包含null值将会减少您在最终结果中显示的dr_name = Mark。要包含只有null值的行,我再次将该连接添加到表中。

+0

你想添加谓词以避免返回空值 – 2013-05-02 14:09:39

+0

@DavidAldridge你是对的,我稍微修改了它,因为它们实际上是想返回所有'DR_NAME'值。如果我排除'null',那么他们将不会得到'Mark' – Taryn 2013-05-02 14:14:31

+0

@ user2249376我不确定你的意思?我根据您的示例显示了每个dr_name的多行 - http://www.sqlfiddle.com/#!4/b8801/10 - Jones有3行,Mark = 1,Smith = 1和Ward = 2 – Taryn 2013-05-02 14:47:06

1

我所知道的最有效的方法就是做一些逻辑交叉联接:在扫描表一次为每个子查询

select * 
from (select t.dr_name, 
      (case when n.n = 1 then acct1 
        when n.n = 2 then acct2 
        when n.n = 3 then acct3 
        when n.n = 4 then acct4 
       end) as acct 
     from t cross join 
      (select 1 as n from dual union all 
      select 2 from dual union all 
      select 3 from dual union all 
      select 4 from dual 
      ) n 
    ) s 
where acct is not null 

union all方法的典型结果。这种方法通常会扫描一次表格。

1

如果您只想插入这些记录,那么看看多重插入 - 对数据和生成的多行进行一次扫描,因此效率非常高。

代码示例在这里:http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9014.htm#SQLRF01604

请注意,您可以参考同一个表多次使用的线沿线的语法...

insert all 
    when acct1 is not null then into target_table (..) values (dr_name,acct1) 
    when acct2 is not null then into target_table (..) values (dr_name,acct2) 
    when acct3 is not null then into target_table (..) values (dr_name,acct3) 
    when acct4 is not null then into target_table (..) values (dr_name,acct4) 
select 
    dr_name, 
    acct1, 
    acct2, 
    acct3, 
    acct4 
from my_table. 
+0

谢谢。我会试试这个。我有一个目前可行的解决方案,但这可能会更有效率。 – user2249376 2013-05-02 19:54:24