【问题标题】:How would I join to a subselect (a scope) using Rails 3 and Arel?如何使用 Rails 3 和 Arel 加入子选择(范围)?
【发布时间】:2011-05-30 04:40:12
【问题描述】:

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

我有一张:phenotypes 的表,它们是has_and_belongs_to_many :genes,它们本身就是has_and_belongs_to_many :orthogroups。因此,表型和邻位群之间的关系是多对多的。

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

  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")
  }

因此,执行Orthogroup.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 (...)",是否可以做到这一点?

【问题讨论】:

    标签: ruby-on-rails-3 named-scope arel sql-subselect


    【解决方案1】:

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

    【讨论】:

    • 哦,我明白你的意思了。是的,我试过用其他名字。这似乎不会影响结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    相关资源
    最近更新 更多