PostgreSQL:现有表中新表中的外键

PostgreSQL:现有表中新表中的外键,sql,postgresql,database-design,foreign-keys,Sql,Postgresql,Database Design,Foreign Keys,我对Postgresql和Python非常陌生,在理解外键时遇到了一些问题(我想这就是我在这里使用的)。我看过一个例子,但我不认为这正是我需要的 作为一个简单的例子,我在现有的表中有一些信息: [ID REFERENCE REF_AGE DATA1 DATA 2] [1 JOHN 50 50 60 ] [2 JOHN 50 55

我对Postgresql和Python非常陌生,在理解外键时遇到了一些问题(我想这就是我在这里使用的)。我看过一个例子,但我不认为这正是我需要的

作为一个简单的例子,我在现有的表中有一些信息:

    [ID      REFERENCE     REF_AGE   DATA1      DATA 2]
    [1       JOHN          50        50         60    ]
    [2       JOHN          50        55         30    ]
    [3       TOM           60        60         10    ]
    [4       MATT          30        76         57    ]
    [5       MATT          30        45         47    ]
我想用这个做两张新桌子。其中一个包括ID和带有引用ID的数据,该引用ID链接到另一个新表-引用表,我可以在其中存储关于每个引用的其他信息(例如上面的年龄)

表1:

    [ID      REF_ID        DATA1      DATA 2]
    [1       1             50         60    ]
    [2       1             55         30    ]
    [3       2             60         10    ]
    [4       3             76         57    ]
    [5       3             45         47    ]
表2:

    [REF_ID     NAME    AGE  ]
    [1          JOHN    50   ]
    [2          TOM     60   ]
    [3          MATT    30   ]

有人能告诉我如何像这样分割现有数据吗?将原始表参考列中的唯一值分离到新的参考表中,并将相应的参考id插入到另一个新表中。

有配方。但是如果人名不是唯一的,则会出现问题

drop table if exists not_normalized cascade;
create table not_normalized (
    id int, reference text, ref_age int, data1 int, data2 int
);

insert into not_normalized (id, reference, ref_age, data1, data2) values
(1,'JOHN',50,50, 60    ),
(2,'JOHN',50,55, 30    ),
(3,'TOM',60,60, 10    ),
(4,'MATT',30,76, 57    ),
(5,'MATT',30,45, 47    ),
(6,null,null,42,50);

drop table if exists referenced cascade;
create table referenced (
    ref_id serial primary key,
    name text,
    age int
);
选择不同的对(名称、年龄)可以最大限度地减少名称冲突问题:

insert into referenced (name, age)
select distinct reference, ref_age
from not_normalized
where (reference, ref_age) is not null
;
table referenced;
 reference | ref_age 
-----------+---------
 JOHN      |      50
 TOM       |      60
 MATT      |      30

drop table if exists referencer;
create table referencer (
    id serial primary key,
    ref_id int references referenced (ref_id),
    data1 int, data2 int
);
再次使用年龄来最小化碰撞:

insert into referencer (ref_id, data1, data2)
select r.ref_id, data1, data2
from
    not_normalized nn
    left join
    referenced r on r.name = nn.reference and r.age = nn.ref_age
;
table referencer;
 id | ref_id | data1 | data2 
----+--------+-------+-------
  1 |      1 |    50 |    60
  2 |      1 |    55 |    30
  3 |      3 |    76 |    57
  4 |      3 |    45 |    47
  5 |      2 |    60 |    10
  6 |        |    42 |    50

这是食谱。但是如果人名不是唯一的,则会出现问题

drop table if exists not_normalized cascade;
create table not_normalized (
    id int, reference text, ref_age int, data1 int, data2 int
);

insert into not_normalized (id, reference, ref_age, data1, data2) values
(1,'JOHN',50,50, 60    ),
(2,'JOHN',50,55, 30    ),
(3,'TOM',60,60, 10    ),
(4,'MATT',30,76, 57    ),
(5,'MATT',30,45, 47    ),
(6,null,null,42,50);

drop table if exists referenced cascade;
create table referenced (
    ref_id serial primary key,
    name text,
    age int
);
选择不同的对(名称、年龄)可以最大限度地减少名称冲突问题:

insert into referenced (name, age)
select distinct reference, ref_age
from not_normalized
where (reference, ref_age) is not null
;
table referenced;
 reference | ref_age 
-----------+---------
 JOHN      |      50
 TOM       |      60
 MATT      |      30

drop table if exists referencer;
create table referencer (
    id serial primary key,
    ref_id int references referenced (ref_id),
    data1 int, data2 int
);
再次使用年龄来最小化碰撞:

insert into referencer (ref_id, data1, data2)
select r.ref_id, data1, data2
from
    not_normalized nn
    left join
    referenced r on r.name = nn.reference and r.age = nn.ref_age
;
table referencer;
 id | ref_id | data1 | data2 
----+--------+-------+-------
  1 |      1 |    50 |    60
  2 |      1 |    55 |    30
  3 |      3 |    76 |    57
  4 |      3 |    45 |    47
  5 |      2 |    60 |    10
  6 |        |    42 |    50

谢谢你这正是我需要的!然而,我后来又遇到了另一个问题。假设我们向not_normalized添加另一行,该行包含data1和data2,但没有引用(或ref_age),这些列现在为NULL。你是怎么处理的?referencer输出似乎完全忽略了这一行,我认为这与尝试使用NULL连接有关。@user6789594将
内部连接更改为
[outer]左连接。更新的答案。很抱歉很难回答,我真的不想再问一个问题。我遇到过一个实例,其中名称将被填充,例如“Peter”,但年龄将为空。有没有办法处理这个案子并给它一个参考号?引用表中的年龄是否只有NULL?(reference,ref_age)似乎不为null,如果其中任何一列为null,则总是返回null;因为我实际上将这些列(远不止这些)称为%s。e、 g.
插入到%s(%s)中选择与%s不同的%s,其中(%s)_tbl_导入、列集、列集、列集导出、列集
谢谢这正是我需要的!然而,我后来又遇到了另一个问题。假设我们向not_normalized添加另一行,该行包含data1和data2,但没有引用(或ref_age),这些列现在为NULL。你是怎么处理的?referencer输出似乎完全忽略了这一行,我认为这与尝试使用NULL连接有关。@user6789594将
内部连接更改为
[outer]左连接。更新的答案。很抱歉很难回答,我真的不想再问一个问题。我遇到过一个实例,其中名称将被填充,例如“Peter”,但年龄将为空。有没有办法处理这个案子并给它一个参考号?引用表中的年龄是否只有NULL?(reference,ref_age)似乎不为null,如果其中任何一列为null,则总是返回null;因为我实际上将这些列(远不止这些)称为%s。e、 g.
插入到%s(%s)中选择与%s不同的%s,其中(%s)_tbl_导入、列_集、列_集、列_导出、列_集