我正在使用Django,我需要使用多个模型来过滤数据的查询集。这些模型具有相同的外键字段。
示例:
class Snp(models.Model): chromosome = models.IntegerField() position = models.IntegerField() class Variant(models.Model): snp = models.ForeignKey(Snp, on_delete=models.CASCADE) genotype = models.IntegerField() class Mutation(models.Model): snp = models.ForeignKey(Snp, on_delete=models.CASCADE) synonymous = models.IntegerField() class Annot(models.Model): snp = models.ForeignKey(Snp, on_delete=models.CASCADE) gene = models.IntegerField()
q = Variant.objects.prefetch_related('snp').filter(snp__mutation__synonymous =1,snp__annot__gene=2) print(q.query)
这可能会创建以下SQL:
SELECT "md_variant"."id", "md_variant"."snp_id", "md_variant"."genotype" FROM "md_variant" INNER JOIN "md_snp" ON ("md_variant"."snp_id" = "md_snp"."id") INNER JOIN "md_annot" ON ("md_snp"."id" = "md_annot"."snp_id") INNER JOIN "md_mutation" ON ("md_snp"."id" = "md_mutation"."snp_id") WHERE ("md_annot"."gene" = 2 AND "md_mutation"."synonymous" = 1)
我使用了比上面更快的简化SQL,并得到了相同的结果:
SELECT "md_variant"."id", "md_variant"."snp_id", "md_variant"."genotype" FROM "md_variant" INNER JOIN "md_annot" ON ("md_variant"."snp_id" = "md_annot"."snp_id") INNER JOIN "md_mutation" ON ("md_variant"."snp_id" = "md_mutation"."snp_id") WHERE ("md_annot"."gene" = 2 AND "md_mutation"."synonymous" = 1)
我认为内部联接md_snp是不必要的,因为同一模型Snp的Mutation,Variant和Annot模型外键。如何删除此多余的内部联接?
答案 0 :(得分:0)
首先prefetch_related()
在这里没有意义。
q = Variant.objects.filter(snp__mutation__synonymous=1, snp__annot__gene=2)
print(q.query)
您无法避免Join
的Snp,因为您有ForeignKey
到 SNP 。如果您认为您的sql查询更好,请执行原始sql查询。没问题。