在Oracle中呈现数据的方法

时间:2018-09-03 05:17:13

标签: oracle join oracle11g

我需要一种避免来自oracle联接的重复数据的方法,每个值只显示一次,我有这种情况。

第一个表格包含有关某个人的一般信息。

+-----------+-------+-------------+
| ID        | Name  | Birtday_date|
+-----------+-------+-------------+
| 1         | Byron | 12/10/1998  |
| 2         | Peter | 01/11/1973  |
| 4         | Jose  | 05/02/2008  |
+-----------+-------+-------------+

第二个表包含有关第一个表中某人电话的信息数据。

+-------+----------+----------+----------+
| ID    |ID_Person |CELL_TYPE | NUMBER   |
+-------+- --------+----------+----------+
| 1221  | 1        | 3        | 099141021|
| 2221  | 1        | 2        | 099091925|
| 3222  | 1        | 1        | 098041013|
| 4321  | 2        | 1        | 088043153|
| 4561  | 2        | 2        | 090044313|
| 5678  | 4        | 1        | 092049013|
| 8990  | 4        | 2        | 098090233|
+----- -+----------+----------+----------+

第三张表包含有关第一张表中人员电子邮件的信息数据。

+------+----------+----------+---------------+
| ID   |ID_Person |EMAIL_TYPE| Email         |
+------+- --------+----------+---------------+
| 221  | 1        | AC1      |jdoe@aol.com   |
| 222  | 1        | AB2      |jdoe1@aol.com  |
| 421  | 2        | AC1      |xx12@yahoo.com |
| 451  | 2        | AB2      |dsdsa@gmail.com|
| 578  | 4        | AC1      |sasaw1@sdas.com|
| 899  | 4        | AB2      |cvcvsd@wew.es  |
| 899  | 4        | AB2      |cvsd@www.es    |
+------+----------+----------+---------------+

如果使用joins,结果将是这样。

+-----+-------+-------------+----------+----------+----------+----------------+
| ID  | Name  | Birtday_date| CELL_TYPE|  NUMBER  |EMAIL_TYPE|EMAIL           |
+-----+-------+-------------+----------+----------+----------+----------------+
| 1   | Byron | 12/10/1998  | 3        | 099141021|AC1       |jdoe@aol.com    |   
| 1   | Byron | 12/10/1998  | 3        | 099141021|AB2       |jdoe1@aol.com   |  
| 1   | Byron | 12/10/1998  | 2        | 099091925|AC1       |jdoe@aol.com    |   
| 1   | Byron | 12/10/1998  | 2        | 099091925|AB2       |jdoe1@aol.com   | 
| 1   | Byron | 12/10/1998  | 1        | 098041013|AC1       |jdoe@aol.com    |   
| 1   | Byron | 12/10/1998  | 1        | 098041013|AB2       |jdoe1@aol.com   | 
| 2   | Peter | 01/11/1973  | 1        | 088043153|AC1       |xx12@yahoo.com  |
| 2   | Peter | 01/11/1973  | 1        | 088043153|AC1       |dsdsa@gmail.com |
| 2   | Peter | 01/11/1973  | 2        | 090044313|AC1       |xx12@yahoo.com  |
| 2   | Peter | 01/11/1973  | 2        | 090044313|AC1       |dsdsa@gmail.com |
| 4   | Jose  | 05/02/2008  | 1        | 092049013|AC1       |sasaw1@sdas.com |
| 4   | Jose  | 05/02/2008  | 1        | 092049013|AC1       |cvcvsd@wew.     |
| 4   | Jose  | 05/02/2008  | 1        | 092049013|AC1       |cvsd@www.es     |
| 4   | Jose  | 05/02/2008  | 2        | 098090233|AB2       |sasaw1@sdas.com |
| 4   | Jose  | 05/02/2008  | 2        | 098090233|AB2       |cvcvsd@wew.es   |
| 4   | Jose  | 05/02/2008  | 2        | 098090233|AB2       |cvsd@www.es     |    
+-----+-------+-------------+----------+----------+----------+----------------+

我期望的结果是这样的。

+-----+-------+-------------+----------+----------+----------+----------------+
| ID  | Name  | Birtday_date| CELL_TYPE|  NUMBER  |EMAIL_TYPE|EMAIL           |
+-----+-------+-------------+----------+----------+----------+----------------+
| 1   | Byron | 12/10/1998  | 3        | 099141021|AC1       |jdoe@aol.com    |   
| 1   | Byron | 12/10/1998  | 2        | 099091925|AB2       |jdoe1@aol.com   | 
| 1   | Byron | 12/10/1998  | 1        | 099091925|          |                | 
| 2   | Peter | 01/11/1973  | 1        | 088043153|AC1       |xx12@yahoo.com  |
| 2   | Peter | 01/11/1973  | 2        | 090044313|AB2       |dsdsa@gmail.com |
| 4   | Jose  | 05/02/2008  | 1        | 092049013|AC1       |sasaw1@sdas.com |
| 4   | Jose  | 05/02/2008  | 2        | 098090233|AB2       |cvcvsd@wew.es   |
| 4   | Jose  | 05/02/2008  |          |          |AB2       |cvsd@www.es     |
+-----+-------+-------------+----------+----------+----------+----------------+

这是我需要呈现数据的方式。

2 个答案:

答案 0 :(得分:2)

您要实现的目标是:

select p.id
       , p.name
       , cursor ( select t.cell_type, t.cell
                from phones  t
            where t.id_person = p.id
            order by t.id    )
       , cursor ( select e.email_type, e.email
                from emails  e
            where e.id_person = p.id
            order by e.id    )
from person p 
;

障碍在于您使用的客户端是否能够渲染a nested cursor。在我的实验中,SQL Fiddle和Oracle LiveSQL都被淘汰了(尽管有趣的是SQL Fiddle比LiveSQL更优美)。

但是,如果您想要一个可以在任何客户端中运行的纯SQL解决方案,这里是一个:

with t as ( 
       select x.*
              , row_number() over (partition by x.id_person order by x.id) as rn
       from phones x ) 
   , e as ( 
       select x.*
              , row_number() over (partition by x.id_person order by x.id) as rn
       from emails x )
   , nos as (
       select rn from t 
       union select rn from e 
     )
select p.id
       , p.name
       , t.cell_type
       , t.cell
       , e.email_type
       , e.email
from person p 
     cross join nos
     left outer join t
            on t.id_person = p.id
            and t.rn = nos.rn
     left outer join  e
            on e.id_person = p.id
            and e.rn = nos.rn
where e.rn is not null 
or t.rn is not null            
order by p.id, nos.rn
;

这将为EMAILS和PHONES子查询生成行号。然后,它生成一个行号列表,该行号将应用于PERSON结果,并提供一个框架,在该框架上我们可以从子查询中左移JOIN结果。

Here is a SQL Fiddle demo

答案 1 :(得分:2)

除了APC的答案外,您还可以假设电话和电子邮件表中的id_person列是人员表中id列的外键,首先可以对电话和电子邮件表进行完全外部联接,将其加入个人表之前,例如:

with t as ( select x.*
                   , row_number() over (partition by x.id_person order by x.id) as rn
            from phones x ) 
   , e as ( select x.*
                        , row_number() over (partition by x.id_person order by x.id) as rn
                from emails x )
   , et as (
     select coalesce (e.id_person, t.id_person) id_person,
            t.cell_type,
            t.cell,
            e.email_type,
            e.email,
            coalesce(e.rn, t.rn) rn
     from   t
     full outer join e on t.id_person = e.id_person and t.rn = e.rn
     )
select p.id
       , p.name
       , et.cell_type
       , et.cell
       , et.email_type
       , et.email
from person p 
     inner join et on et.id_person = p.id
order by p.id, et.rn;

SQLfiddle:http://sqlfiddle.com/#!4/c4c0c/4

如果我是您,我将对此进行测试,并通过APC的答案进行测试,看看哪种方法最适合您的实际数据。