Sql 如何在Oracle 10g中将多个列值作为新行返回?

Sql 如何在Oracle 10g中将多个列值作为新行返回?,sql,oracle10g,Sql,Oracle10g,我有一个表,其中多个帐号与不同的ID(DR_NAME)关联。每个帐户最多可以有0个帐户,最多可以有16个。我相信UNPIVOT会起作用,但我使用的是Oracle 10g,它不支持这一点 DR_NAME ACCT1 ACCT2 ACCT3 ACC4 ====================================== SMITH 1234 JONES 5678 2541 2547 MARK NULL WARD 87

我有一个表,其中多个帐号与不同的ID(DR_NAME)关联。每个帐户最多可以有0个帐户,最多可以有16个。我相信UNPIVOT会起作用,但我使用的是Oracle 10g,它不支持这一点

DR_NAME   ACCT1   ACCT2   ACCT3   ACC4  
======================================
SMITH     1234
JONES     5678    2541    2547
MARK      NULL    
WARD      8754    6547
我想为每个名称显示一个新行,每行仅显示一个帐号

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

Oracle 10g没有
UNPIVOT
功能,但您可以使用
UNION ALL
查询将列取消pivot到行中:

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;


此查询使用
UNION ALL
将列转换为行。我包括了一个
where
子句来删除任何
null
值,否则您将为每个帐户获得多行,其中帐户值为null。排除
null
值将删除您在最终结果中显示的
dr_name=Mark
。为了包含只有
null
值的行,我再次将联接添加到表中。

Oracle 10g没有
UNPIVOT
功能,但您可以使用
UNION ALL
查询将列取消pivot到行中:

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;


此查询使用
UNION ALL
将列转换为行。我包括了一个
where
子句来删除任何
null
值,否则您将为每个帐户获得多行,其中帐户值为null。排除
null
值将删除您在最终结果中显示的
dr_name=Mark
。为了包含只有
null
值的行,我再次将连接添加到表中。

我知道的最有效的方法是使用一些逻辑进行交叉连接:

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
方法的典型结果是为每个子查询扫描一次表。这种方法通常会扫描一次表。

我知道的最有效的方法是使用一些逻辑进行交叉连接:

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
方法的典型结果是为每个子查询扫描一次表。这种方法通常会扫描表一次。

如果您只对插入这些记录感兴趣,那么请看一下multitable insert——对数据进行一次扫描并生成多行,因此非常有效

此处的代码示例:

请注意,您可以多次引用同一个表,使用以下语法行

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.

若您只对插入这些记录感兴趣,那个么请看一下multitable insert——对数据进行一次扫描并生成多行,所以它非常高效

此处的代码示例:

请注意,您可以多次引用同一个表,使用以下语法行

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.

在一个查询中,您需要为多少行数据执行此操作,您需要选择此数据还是将其插入表中?@davidardridge大约1500行初始数据,我估计,当每个DR_名称仅与一个帐户配对时,可能会产生大约6000行。它需要插入到一个表中。在一个查询中,您需要为多少行数据执行此操作,您需要只选择此数据还是将其插入表中?@davidridge大约1500行初始数据,我估计,当每个DR_名称仅与一个ACCT配对时,可能会产生大约6000行。它需要插入到一个表中,您可能希望添加谓词以避免返回nulls@DavidAldridge你是对的,我稍微修改了一下,因为他们实际上想要返回所有
DR\u NAME
值。如果我排除
null
,那么他们将不会得到
标记
@user2249376我不知道你的意思是什么?我根据您的样本为每个dr_姓名显示多行--Jones有3行,Mark=1,Smith=1,Ward=2@bluefeet我会检查我的代码。这似乎确实有效。我真的很感谢你的帮助。@bluefeet收到了!我没有读我所有的结果。我使用的是Toad,必须添加“orderby”子句来将DR_名称分组。您可能希望添加谓词以避免返回nulls@DavidAldridge你是对的,我稍微修改了一下,因为他们实际上想要返回所有
DR\u NAME
值。如果我排除
null
,那么他们将不会得到
标记
@user2249376我不知道你的意思是什么?我根据您的样本为每个dr_姓名显示多行--Jones有3行,Mark=1,Smith=1,Ward=2@bluefeet我会检查我的代码。这似乎确实有效。我真的很感谢你的帮助。@bluefeet收到了!我没有读我所有的结果。我用的是蟾蜍,不得不加上“orderby”子句来把医生的名字组合在一起谢谢。我试试这个。我有一个目前有效的解决方案,但这可能更有效。谢谢。我试试这个。我有一个目前有效的解决方案,但这可能更有效。