我需要一种避免来自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 |
+-----+-------+-------------+----------+----------+----------+----------------+
这是我需要呈现数据的方式。
答案 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结果。
答案 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的答案进行测试,看看哪种方法最适合您的实际数据。