我正在建立一个具有相互关联的表的数据库,问题是我使用的索引方法似乎犯了某些错误,因为某些索引引用了表之间的不同行。
我有一个遗传标记数据集,具有1'405.301(SNPs)行和3092列(基因型),每个SNP均由染色体,其内部位置以及具有SNP的其他等位基因识别。
我尝试将整个数据集上载到表中,但超出了psql中表的最大列限制,因此我将数据集分为一系列子集。每个子集都有某些列,另一些则可以帮助我识别每一行(SNP)。因此,我编写了一个python sqlachemy脚本,该脚本使用与数据集对应子集相同的列名称创建一个空表。之后,我使用psql命令COPY转储对应表的每个子集,并为每个表创建了一个自动增量索引作为主键。
当我在不同表的数据之间进行比较时出现问题,因为索引引用了表之间的不同行
这是转储子集并设置每个表的索引的psql代码
COPY p11 FROM '/home/pybonacci/Documentos/.../p11.csv' WITH (HEADER true, format csv, DELIMITER E'\t');
ALTER TABLE p11
ADD COLUMN marker_id serial primary key;
我意识到使用此代码在表的某些部分中出现了索引问题
select
p11.marker_id, p11."ALT", p11."POS", p08.marker_id, p08."ALT", p08."POS"
from
p11
inner join
p08 on p08.marker_id = p11.marker_id
where
p11.marker_id > 1710
order by
p11.marker_id
limit 100
输出:
p11.marker_id p11.ALT p11.POS p08.marker_id p08.ALT p08.POS
1716 T 390961 1716 T 390961
1717 G 390963 1717 G 390963
1718 A 390969 1718 A 390969
1719 T 392223 1719 AG 391838
1720 CT 392240 1720 T 391847
1721 AG 391838 1721 A 391864
1722 T 391847 1722 G 391876
1723 A 391864 1723 A 391881
我希望此查询的输出为空。
我希望清楚一点,对我的英语不好对不起
答案 0 :(得分:0)
虽然不是不可能,但跨表同步自动生成的serial
值可能会是一个挑战。
我将以不同的方式来处理。
表中的最大列数是您无法真正摆脱的硬限制。此外,该限制还适用于单个查询可以返回的列数。因此,即使将数据集拆分为多个表,也无法访问同一查询中的所有SNP,因为联接所有表将返回超出最大列数的结果。
因此,您需要找到其他方式来存储它。
除非您可以完全更改输入文件的结构,否则我将把该文件导入到具有单个列的表中,然后使用Postgres字符串和数组函数拆分数据。
首先将原始文件加载到仅包含一个text
列的表中。
create unlogged table import_table
(
line text
);
导入文件时,您需要使用一个字符作为分隔符,输入文件中不会出现该字符,以便copy
将所有内容视为一行:
copy import_table from '....' WITH (HEADER true, format text, DELIMITER '§');
我不知道数据中是否可以出现§
-您需要找到一个合适的字符。不可打印字符也可能会起作用,例如:e'\x01'
数据在那里后,您可以将行转换为数组(使用string_to_array()
)并分别访问每个元素(列),例如将行插入到第一个“子集”表中:
insert into p01 (marker_id, alt_1, pos_1, chromosom_1, alt_2, pos_2, chromosom_2, ...)
select c[1]::int as marker_id,
c[2] as alt_1,
c[3] as pos_1,
c[4] as chromosom_1,
c[5] as alt_2,
c[6] as pos_2,
c[7] as chromosom_2,
....
from (
select string_to_array(line, E'\t') as c
from import_table
) t;
对于其他“子集标签”也是如此。如果需要,可以使用PL / pgSQL过程将其自动化。
但是再次:您不能将所有这些表连接在一起以得到所有结果的单一结果,因为这又将超出最大列数。
根据以后需要访问数据的方式,还有其他选项可以将所有行保留在一个表中。
一种解决方案是创建一个包含三个字段的自定义类型snp_type
,然后创建一个包含1000个该类型列的表:
create type snp_type as
(
alt text,
pos integer,
chromosome text
);
create table data
(
marker_id integer,
snp_1 snp_type,
snp_2 snp_type,
snp_3 snp_type,
...
);
然后使用如下所示的内容从导入表中填充该表:
insert into p01 (marker_id, snp_1, snp_2, ...)
select c[1]::int as marker_id,
(c[2], c[3]::int, c[4])::snp_type as snp_1,
(c[5], c[6]::int, c[7])::snp_type as snp_2,
(c[8], c[9]::int, c[10])::snp_type as snp_3,
....
from (
select string_to_array(line, E'\t') as c
from import_table
) t;
同样,这可以使用PL / pgSQL自动执行。
一旦有了snp_type
,您还可以考虑将所有这些值存储到作为该类型数组的单个列中:
create type snp_type as
(
alt text,
pos integer,
chromosome text
);
create table data
(
marker_id integer,
snps snp_type[]
);
插入内容将如下所示:
insert into p01 (marker_id, snp_1, snp_2, ...)
select c[1]::int as marker_id,
array
[
(c[2], c[3]::int, c[4])::snp_type,
(c[5], c[6]::int, c[7])::snp_type,
(c[8], c[9]::int, c[10])::snp_type,
....
]
from (
select string_to_array(line, E'\t') as c
from import_table
) t;
这也可以使用PL / pgSQL自动化
上面的所有代码只是一个粗略的草图,其中可能有错误。这样做的目的是为您提供起点和关于您可以做什么的想法。