我想在执行之前将条件子句附加到mysql命令,这将根据我想从数据库中提取的元素数量而有所不同。
例如,我有大量基因列表,对于每个感兴趣的基因,我都有所有外显子的坐标。
Gene_ID外显子开始结束
geneA exon1 325 359
geneA exon2 554 601
geneB exon1 870 900
geneB exon2 990 1010
geneB exon3 1200 1350
如您所见,geneA有2个外显子,geneB有3个外显子。我想执行如下命令来返回外显子坐标内DB的所有元素的计数。
select count(*) from db_x where position between exon1_start and exon1_end and position between exon2_start and exon2_end;
由于每个基因中的外显子数量不同(一些基因可以包含数十个外显子),我需要在执行整体之前为每个外显子添加额外的“和exon_end和exon_start之间的位置”条件语句命令。
我正在努力想出一个合乎逻辑的解决方案。对于每个基因,我将一个连接的start_end位置列表传递给一个函数,然后查询mysql服务器。例如,对于geneA ['325..359','554..601']
我正在使用的命令(将光标向上设置后)如下所示;
cur.execute('select count(*) from db_x where position between '+str(exon1_start)+' and '+str(exon1_end)+' and position between +'str(exon2_start)+' and '+str(exon2_end))
如果它只是一个或两个外显子就可以了,但是我如何处理可能很长的外显子列表呢?如何在执行之前动态重新格式化命令?
真的很感激一些帮助,因为我很难过!
答案 0 :(得分:0)
您可以动态构建一个存储外显子数据的字典,并根据这样的字典构建SQL查询:
gene_exons_dict = dict()
def add_exon_to_gene(gene_name,gene_exon):
if gene_name not in gene_exons_dict:
gene_exons_dict[gene_name] = []
tmp_exons_dict = {'start': gene_exon[0], 'end': gene_exon[1]}
gene_exons_dict[gene_name].append(tmp_exons_dict)
def get_sql_query_for_gene(gene_name):
if gene_name not in gene_exons_dict:
raise Exception("exons not defined for gene: %s" % gene_name)
sql_query = 'select count(*) from db_x.tb_y WHERE '
exons_count = len(gene_exons_dict[gene_name])
for exon_data in gene_exons_dict[gene_name]:
sql_query += '(position >'+str(exon_data['start'])+' AND position <'+str(exon_data['end'])+')'
if exons_count > 1:
sql_query += ' AND ' # change it to OR if query should return sum of sets instead of their intersection
# removing last and for multi-exons case
if exons_count > 1:
sql_query=sql_query[:-5]
return sql_query
if __name__ == '__main__':
add_exon_to_gene('gene1', [1, 2])
add_exon_to_gene('gene1', [3, 8])
add_exon_to_gene('gene1', [10, 15])
add_exon_to_gene('gene2', [20, 25])
print get_sql_query_for_gene('gene1')
print get_sql_query_for_gene('gene2')
给出输出:
C:\tmp>python dynamicDictTest.py
select count(*) from db_x.tb_y WHERE (position >1 AND position <2) AND (position >3 AND position <8) AND (position >10 AND position <15)
select count(*) from db_x.tb_y WHERE (position >20 AND position <25)