2

我需要将一个表加入到 select/group-by 查询(包括同一个表)中,我想使用 Arel 来完成。

我有一个表:phenotypes其中是has_and_belongs_to_many :genes,哪些是他们自己has_and_belongs_to_many :orthogroups。因此,表型和邻位群之间的关系是多对多的。

我有两个范围(在正交组上),它们获取与特定表型相关的所有正交组:

  scope :with_phenotype, lambda { |phenotype_id|
    where("observations.phenotype_id = ?", phenotype_id).
      joins("inner join orthologies on (orthologies.orthogroup_id = orthogroups.id) inner join observations on (observations.gene_id = orthologies.gene_id)")
  }

  scope :with_associated_gene_ids_for_phenotype, lambda { |phenotype_id|
    with_phenotype(phenotype_id).
      select("orthogroups.id, array_agg(distinct observations.gene_id) as associated_gene_ids").
      group("orthogroups.id")
  }

因此,doingOrthogroup.with_associated_gene_ids_for_phenotype(48291)应该返回一个正交组 ID 表以及将它们与表型联系起来的基因。

那东西一切正常。

问题是我想获取其余部分orthogroups.*并将其加入第二个范围的结果,因此基因列表基本上就像我的 Orthogroup ActiveRecord 模型上的一个额外字段。

大致是这样的:

SELECT   o1.*, o_genes.associated_gene_ids
FROM     orthogroups o1
INNER JOIN (
  SELECT    o2.id, array_agg(DISTINCT obs.gene_id) AS associated_gene_ids
  FROM orthogroups o2
  INNER JOIN orthologies ortho ON (ortho.orthogroup_id = o2.id)
  INNER JOIN observations obs ON (ortho.gene_id = obs.gene_id)
  WHERE obs.phenotype_id = ? GROUP BY o2.id
) AS o_genes
ON (o1.id = o_genes.id);

现在,该查询似乎起作用了。但我更愿意找到一种方法将 Orthogroup 表直接加入它自己的范围以获取这些基因。

也许使用 SQL 会更简单,但似乎 Arel 应该有一个简单的方法。我发现了几个类似的问题,但似乎都没有答案。

我找到的最接近的解决方案是:

def self.orthogroups phenotype_id
  Orthogroup.select("orthogroups.*, o_genes.associated_gene_ids").
    joins(Arel.sql("inner join (" + Orthogroup.with_associated_gene_ids_for_phenotype(phenotype_id).to_sql + ") AS o_genes ON (o_genes.id = orthogroups.id)"))
end

输出的 SQL 在两个上下文中使用表“正交组”,这让我很担心;但是,对结果的抽查表明查询是正确的。

尽管如此,这并不是我所希望的优雅解决方案。没有尴尬就可以做到这一点"inner join (...)"吗?

4

1 回答 1

0

仅仅从您的代码的第一眼看:您是否尝试将方法和局部变量“正交组”重命名为不同的名称,因为您有同名的关系?

于 2011-01-03T12:16:27.737 回答