SQL 查询连接这 3 个表以删除虚假行 - OWNER、TYPE、PERSON
SQL query to join these 3 tables to remove spurious rows - OWNER, TYPE, PERSON
我在加入这 3 个 table 时遇到了一些问题。
Table1
OWNER TYPE
O1 T1
O1 T2
O2 T1
Table2
OWNER PERSON
O1 P1
O1 P2
O2 P1
Table3
TYPE PERSON
T1 P1
T2 P2
T1 P2
我想对所有 3 个 table 进行连接,所以我的输出将是:
FinalTable
OWNER TYPE PERSON
O1 T1 P1
O1 T2 P2
O2 T1 P2
O1 T1 P2
我基本上是在演示 5NF 如何删除虚假行。当我加入 table 的任意 2 个组合时,我会得到额外的数据(这是我所期望的)。
虽然我很难加入第三个 table,但我从来没有需要加入所有 3 个。
到目前为止,这是我的查询:
select r1.*, r2.PERSON from table1 r1, table2 r2, table3 r3
where r1.OWNER = r2.OWNER and r2.PERSON = r3.PERSON
我的输出 returns 8 行,有些是重复的。我尝试过查询,但它只会进一步增加行数。
我的查询基于我拥有的一本 ORACLE APEX 教程书,但它没有加入 3 tables,它们的布局与我的一样。
如何加入这 3 个 table 以删除加入 2 后得到的虚假行?
问题是我 link编辑了 3 个表格中的 2 个。我的工作查询如下:
select r1.*, r2.PERSON from table1 r1, table2 r2, table3 r3 where r1.OWNER = r2.OWNER and r1.TYPE = r3.TYPE and r2.PERSON = r3.PERSON
对于浪费社区的时间,我深表歉意,因为这最终归结为我的疏忽,而且我没有完全理解表中存在的 link 必须在查询中表达。
很多人会建议为此使用 JOIN ... ON。
例如
create table t1 as
select 'O1' as owner, 'T1' as type from dual union all
select 'O1', 'T2' from dual union all
select 'O2', 'T1' from dual ;
create table t2 as
select 'O1' as owner, 'P1' as person from dual union all
select 'O1', 'P2' from dual union all
select 'O2', 'P1' from dual ;
create table t3 as
select 'T1' as type, 'P1' as person from dual union all
select 'T2', 'P2' from dual union all
select 'T1', 'P2' from dual ;
查询
select
t1.*
, t2.PERSON
from t1
join t2 on t1.OWNER = t2.OWNER
join t3 on t2.PERSON = t3.PERSON and t1.type = t3.type
;
-- result
OWNER TYPE PERSON
O2 T1 P1
O1 T1 P1
O1 T2 P2
O1 T1 P2
我把 1 2 3 放在每个列名中,看看它们之前在哪个 table 下。
前 3 个查询是您的方法,每个关系中的 1 个被忽略。第 4 种方法将所有 3 个关系都放入。
其中 t1.owner1=t2.owner2 AND t1.type1=t3.type3 忽略 t2.person2-t3.person3
| owner1 | type1 | owner2 | person2 | type3 | person3 |
|--------|-------|--------|---------|-------|---------|
| O1 | T1 | O1 | P1 | T1 | P1 |
| O1 | T1 | O1 | P1 | T1 | P2 |different ppl
| O1 | T1 | O1 | P2 | T1 | P1 |different ppl
| O1 | T1 | O1 | P2 | T1 | P2 |
| O1 | T2 | O1 | P1 | T2 | P2 |different ppl
| O1 | T2 | O1 | P2 | T2 | P2 |
| O2 | T1 | O2 | P1 | T1 | P1 |
| O2 | T1 | O2 | P1 | T1 | P2 |different ppl
其中 t2.owner1=t1.owner2 AND t2.person2=t3.person3 忽略 t1.type1-t3.type3 关系
| owner1 | type1 | owner2 | person2 | type3 | person3 |
|--------|-------|--------|---------|-------|---------|
| O1 | T1 | O1 | P1 | T1 | P1 |
| O1 | T2 | O1 | P1 | T1 | P1 |different types
| O2 | T1 | O2 | P1 | T1 | P1 |
| O1 | T1 | O1 | P2 | T1 | P2 |
| O1 | T2 | O1 | P2 | T1 | P2 |different types
| O1 | T1 | O1 | P2 | T2 | P2 |different types
| O1 | T2 | O1 | P2 | T2 | P2 |
其中 t3.person2=t2.person3 AND t3.type3=t1.type1 忽略 t1.owner1-t2.owner2 关系
| owner1 | type1 | owner2 | person2 | type3 | person3 |
|--------|-------|--------|---------|-------|---------|
| O1 | T1 | O1 | P1 | T1 | P1 |
| O2 | T1 | O1 | P1 | T1 | P1 |different owners
| O1 | T1 | O1 | P2 | T1 | P2 |
| O1 | T2 | O1 | P2 | T2 | P2 |
| O2 | T1 | O1 | P2 | T1 | P2 |different owners
| O1 | T1 | O2 | P1 | T1 | P1 |different owners
| O2 | T1 | O2 | P1 | T1 | P1 |
其中 r1.owner1 = r2.owner2 和 r2.person2 = r3.person3 和 r1.type1 = r3.type3(4 个结果)
| owner1 | type1 | owner2 | person2 | type3 | person3 |
|--------|-------|--------|---------|-------|---------|
| O1 | T1 | O1 | P1 | T1 | P1 |
| O1 | T1 | O1 | P2 | T1 | P2 |
| O1 | T2 | O1 | P2 | T2 | P2 |
| O2 | T1 | O2 | P1 | T1 | P1 |
每一行都是唯一的,每个类型、人和所有者都是相同的行。
忽略关系(例如忽略 person.when person2-person3 关系)时出现不需要的输出,person2s via table2.owner2 和 person3s via table3.type3 都将是添加到结果中,就好像它们是不相关的字段一样。
作为获得 5NF 设计的一部分,您似乎正在无损地将 table 分解为另外 3 个。
规范化涉及将 table 无损分解为 projections/components,然后 自然连接 回到它。
(我们说原始满足特定的 JD(连接依赖),其特征是组件的列集。如果自然连接某些组件出现虚假(子)行,那么它们最终将被删除组件是自然连接的。)
关系自然联接具有 SQL 自然联接语法。 (假设没有空值或重复行,因为关系没有这些。)这使我们从其组件中返回您的原始 table:
select *
from table1
natural join table2
natural join table3
我们可以在共享列的相等性上使用内部联接来编写:
select table1.type, table2.person, table1.owner
from table1
inner join table2
on table1.owner=table2.owner
-- relevant columns are table1.owner, table1.type, table2.person
inner join table3
on table1.type=table3.type
and table2.person=table3.person
-- relevant columns are table1.owner, table1.type, table2.person
(SQL distinct
这里不需要。这是因为自然连接 return 行 1:1 在某个 1:1 对应关系中那些 return 通过关系等值连接及其在 SQL 中通过内部连接的表达式。)
我在加入这 3 个 table 时遇到了一些问题。
Table1
OWNER TYPE
O1 T1
O1 T2
O2 T1
Table2
OWNER PERSON
O1 P1
O1 P2
O2 P1
Table3
TYPE PERSON
T1 P1
T2 P2
T1 P2
我想对所有 3 个 table 进行连接,所以我的输出将是:
FinalTable
OWNER TYPE PERSON
O1 T1 P1
O1 T2 P2
O2 T1 P2
O1 T1 P2
我基本上是在演示 5NF 如何删除虚假行。当我加入 table 的任意 2 个组合时,我会得到额外的数据(这是我所期望的)。
虽然我很难加入第三个 table,但我从来没有需要加入所有 3 个。
到目前为止,这是我的查询:
select r1.*, r2.PERSON from table1 r1, table2 r2, table3 r3
where r1.OWNER = r2.OWNER and r2.PERSON = r3.PERSON
我的输出 returns 8 行,有些是重复的。我尝试过查询,但它只会进一步增加行数。
我的查询基于我拥有的一本 ORACLE APEX 教程书,但它没有加入 3 tables,它们的布局与我的一样。
如何加入这 3 个 table 以删除加入 2 后得到的虚假行?
问题是我 link编辑了 3 个表格中的 2 个。我的工作查询如下:
select r1.*, r2.PERSON from table1 r1, table2 r2, table3 r3 where r1.OWNER = r2.OWNER and r1.TYPE = r3.TYPE and r2.PERSON = r3.PERSON
对于浪费社区的时间,我深表歉意,因为这最终归结为我的疏忽,而且我没有完全理解表中存在的 link 必须在查询中表达。
很多人会建议为此使用 JOIN ... ON。 例如
create table t1 as
select 'O1' as owner, 'T1' as type from dual union all
select 'O1', 'T2' from dual union all
select 'O2', 'T1' from dual ;
create table t2 as
select 'O1' as owner, 'P1' as person from dual union all
select 'O1', 'P2' from dual union all
select 'O2', 'P1' from dual ;
create table t3 as
select 'T1' as type, 'P1' as person from dual union all
select 'T2', 'P2' from dual union all
select 'T1', 'P2' from dual ;
查询
select
t1.*
, t2.PERSON
from t1
join t2 on t1.OWNER = t2.OWNER
join t3 on t2.PERSON = t3.PERSON and t1.type = t3.type
;
-- result
OWNER TYPE PERSON
O2 T1 P1
O1 T1 P1
O1 T2 P2
O1 T1 P2
我把 1 2 3 放在每个列名中,看看它们之前在哪个 table 下。 前 3 个查询是您的方法,每个关系中的 1 个被忽略。第 4 种方法将所有 3 个关系都放入。
其中 t1.owner1=t2.owner2 AND t1.type1=t3.type3 忽略 t2.person2-t3.person3
| owner1 | type1 | owner2 | person2 | type3 | person3 | |--------|-------|--------|---------|-------|---------| | O1 | T1 | O1 | P1 | T1 | P1 | | O1 | T1 | O1 | P1 | T1 | P2 |different ppl | O1 | T1 | O1 | P2 | T1 | P1 |different ppl | O1 | T1 | O1 | P2 | T1 | P2 | | O1 | T2 | O1 | P1 | T2 | P2 |different ppl | O1 | T2 | O1 | P2 | T2 | P2 | | O2 | T1 | O2 | P1 | T1 | P1 | | O2 | T1 | O2 | P1 | T1 | P2 |different ppl
其中 t2.owner1=t1.owner2 AND t2.person2=t3.person3 忽略 t1.type1-t3.type3 关系
| owner1 | type1 | owner2 | person2 | type3 | person3 | |--------|-------|--------|---------|-------|---------| | O1 | T1 | O1 | P1 | T1 | P1 | | O1 | T2 | O1 | P1 | T1 | P1 |different types | O2 | T1 | O2 | P1 | T1 | P1 | | O1 | T1 | O1 | P2 | T1 | P2 | | O1 | T2 | O1 | P2 | T1 | P2 |different types | O1 | T1 | O1 | P2 | T2 | P2 |different types | O1 | T2 | O1 | P2 | T2 | P2 |
其中 t3.person2=t2.person3 AND t3.type3=t1.type1 忽略 t1.owner1-t2.owner2 关系
| owner1 | type1 | owner2 | person2 | type3 | person3 | |--------|-------|--------|---------|-------|---------| | O1 | T1 | O1 | P1 | T1 | P1 | | O2 | T1 | O1 | P1 | T1 | P1 |different owners | O1 | T1 | O1 | P2 | T1 | P2 | | O1 | T2 | O1 | P2 | T2 | P2 | | O2 | T1 | O1 | P2 | T1 | P2 |different owners | O1 | T1 | O2 | P1 | T1 | P1 |different owners | O2 | T1 | O2 | P1 | T1 | P1 |
其中 r1.owner1 = r2.owner2 和 r2.person2 = r3.person3 和 r1.type1 = r3.type3(4 个结果)
| owner1 | type1 | owner2 | person2 | type3 | person3 | |--------|-------|--------|---------|-------|---------| | O1 | T1 | O1 | P1 | T1 | P1 | | O1 | T1 | O1 | P2 | T1 | P2 | | O1 | T2 | O1 | P2 | T2 | P2 | | O2 | T1 | O2 | P1 | T1 | P1 |
每一行都是唯一的,每个类型、人和所有者都是相同的行。
忽略关系(例如忽略 person.when person2-person3 关系)时出现不需要的输出,person2s via table2.owner2 和 person3s via table3.type3 都将是添加到结果中,就好像它们是不相关的字段一样。
作为获得 5NF 设计的一部分,您似乎正在无损地将 table 分解为另外 3 个。
规范化涉及将 table 无损分解为 projections/components,然后 自然连接 回到它。
(我们说原始满足特定的 JD(连接依赖),其特征是组件的列集。如果自然连接某些组件出现虚假(子)行,那么它们最终将被删除组件是自然连接的。)
关系自然联接具有 SQL 自然联接语法。 (假设没有空值或重复行,因为关系没有这些。)这使我们从其组件中返回您的原始 table:
select *
from table1
natural join table2
natural join table3
我们可以在共享列的相等性上使用内部联接来编写:
select table1.type, table2.person, table1.owner
from table1
inner join table2
on table1.owner=table2.owner
-- relevant columns are table1.owner, table1.type, table2.person
inner join table3
on table1.type=table3.type
and table2.person=table3.person
-- relevant columns are table1.owner, table1.type, table2.person
(SQL distinct
这里不需要。这是因为自然连接 return 行 1:1 在某个 1:1 对应关系中那些 return 通过关系等值连接及其在 SQL 中通过内部连接的表达式。)