1

我在加入这 3 张桌子时遇到了一些麻烦。

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 个表进行连接,所以我的输出是:

FinalTable
OWNER     TYPE     PERSON
O1        T1       P1
O1        T2       P2
O2        T1       P2
O1        T1       P2

我基本上是在演示 5NF 如何删除虚假行。当我加入表的任意 2 个组合时,我会得到额外的数据(这是我所期望的)。

不过,我在加入第三张桌子时遇到了困难,我从来不需要加入所有 3 张桌子。

到目前为止,这是我的查询:

select r1.*, r2.PERSON from table1 r1, table2 r2, table3 r3
where r1.OWNER = r2.OWNER and r2.PERSON = r3.PERSON 

我的输出返回 8 行,有些是重复的。我尝试过使用查询,但它只会进一步增加行数。

我的查询基于我拥有的 ORACLE APEX 教程书,但它没有加入像我一样布局的 3 个表。

如何加入这 3 个表以删除加入 2 个表后得到的虚假行?

4

4 回答 4

2

作为获得 5NF 设计的一部分,您似乎正在无损地将一个表分解为 3 个其他表。

规范化涉及无损地将表分解为自然连接回它的投影/组件。

(我们说原始满足以组件的列集为特征的某个JD(连接依赖)。如果虚假(子)行是由于自然连接某些组件而出现的,那么它们最终将在所有组件自然连接后被删除.)

关系自然连接具有 SQL 自然连接语法。(假设没有空值或重复行,因为关系没有这些。)这使我们从其组件中返回您的原始表:

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

一个 sqlfiddle。

distinct(这里不需要SQL 。这是因为自然连接以 1:1 的比例返回行,与关系 equijoin 及其通过内部连接在 SQL 中的表达式返回的行具有一定的 1:1 对应关系。)

于 2018-04-30T05:34:16.327 回答
1

问题是我链接了 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

我很抱歉浪费了社区的时间,因为这最终归结为我的疏忽,我不完全理解必须在查询中表达表中存在的链接。

于 2018-04-29T18:55:36.703 回答
1

许多人会建议为此使用 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
于 2018-04-29T18:57:54.190 回答
-1

我将 1 2 3 放在每个列名中,以查看它们之前在哪个表下。前 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 关系被忽略),通过 table2.owner2 的 person2s 和通过 table3.type3 的 person3s 都将被添加到结果中,就好像它们是不相关的字段一样,会出现不需要的输出。

http://sqlfiddle.com/#!9/52075d/23

于 2018-04-29T18:58:53.567 回答