【问题标题】:What .merge() is doing in this query?.merge() 在这个查询中做了什么?
【发布时间】:2018-10-19 14:15:05
【问题描述】:

我对如何解释这个查询有点困惑,这都是因为merge 的情况,即使在阅读了文档之后也是如此。

我想知道下面对应的SQL查询是什么

Analise.joins(dape: [empresa: :area_atuacao])
       .merge(@dapes)
       .where(analises: { atual: true })
       .pluck('analises.img')

在此查询上调用 to_sql 的输出:

=> "SELECT \"analises\".* 
    FROM \"analises\" 
    INNER JOIN \"dapes\" ON \"dapes\".\"id\" = \"analises\".\"dape_id\" 
    INNER JOIN \"empresas\" ON \"empresas\".\"id\" = \"dapes\".\"empresa_id\" 
    INNER JOIN \"areas_atuacao\" ON \"areas_atuacao\".\"id\" = \"empresas\".\"area_atuacao_id\" 
    WHERE \"analises\".\"atual\" = 't'"

【问题讨论】:

  • 您能帮我一个忙,然后运行您在最后使用 .to_sql 命令提供的代码吗?如果您了解如何阅读 SQL 查询,那么这可能会有所帮助,但是为了给您具体的答案,我可以使用它。所以只需运行以下代码并让我知道输出:Analise.joins(dape: [empresa: :area_atuacao]).merge(@dapes).where(analises: { atual: true }).pluck('analises.img').to_sql 我可以在这里为您收集一些信息,看看。 Active Record Queries
  • => "SELECT \"analises\".* FROM \"analises\" INNER JOIN \"dapes\" ON \"dapes\".\"id\" = \"analises\" .\"dape_id\" INNER JOIN \"empresas\" ON \"empresas\".\"id\" = \"dapes\".\"empresa_id\" INNER JOIN \"areas_atuacao\" ON \"areas_atuacao\" .\"id\" = \"empresas\".\"area_atuacao_id\" WHERE \"analises\".\"atual\" = 't'" 这真是太棒了伙计!现在我能理解了,tks!
  • 我对 '.merge(@dapes)' @dapes 是 ActiveRecord_Relation 感到困惑,但查询的作用是什么?
  • 阅读我的回答,如果有帮助请告诉我。

标签: sql ruby-on-rails activerecord rails-activerecord


【解决方案1】:

合并(其他)
如果 other 是 ActiveRecord::Relation,则合并其他条件。
- Rails API Docs

一个常见的例子是使用它来合并搜索条件:

@cities = City.all
@cities = @cities.merge(City.where(country: params[:country])) if params[:country]
@cities = @cities.merge(City.where(name: params[:name])) if params[:name]

您还可以使用它在连接表上创建条件,例如文档中的此示例:

Post.where(published: true)
    .joins(:comments)
    .merge( Comment.where(spam: false) )

这将创建与以下相同的查询:

Post.where(published: true)
    .joins(:comments)
    .where(comments: { spam: false })

您示例中的确切查询取决于实例变量@dapes 中定义的范围。但是从生成的 SQL 来看.merge(@dapes) 似乎什么都不做。例如@dapes = Dape.all 可能就是这种情况。

合并一个没有 where 子句的条件什么都不做:

irb(main):003:0> User.merge(User.all)
  User Load (0.6ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):004:0> 

【讨论】:

    【解决方案2】:

    为了更好的可读性,您的格式更好。合并用于转移您的条件,以便不会覆盖任何内容。

    SELECT analises.* 
    FROM analises
        INNER JOIN dapes ON dapes.id = analises.dape_id
        INNER JOIN empresas ON empresas.id = dapes.empresa_id
        INNER JOIN areas_atuacao ON areas_atuacao.id = empresas.area_atuacao_id
    WHERE analises.atual = 't'
    

    似乎.merge() 在您加入表格时使用,以更具体地说明您要加入的内容。

    在这种情况下,您是 .merge(@dapes) 似乎正在将您的表合并到 @dapes 的所有值上。

    更好地了解 .merge(@dapes) 对您的查询产生什么影响的一种方法是再次运行 to_sql 命令,该命令是如何更改 sql 的。

    脚注

    我将您运行的第一个to_sql 生成的sql 输入到Scuttle Editor 并得到以下rails 命令。我不知道这是否有帮助,但我只是认为这是值得深思的!

    Analise.select(Analise.arel_table[Arel.star]).where(Analise.arel_table[:atual].eq('t')).joins(
      Analise.arel_table.join(Dape.arel_table).on(
        Dape.arel_table[:id].eq(Analise.arel_table[:dape_id])
      ).join_sources
    ).joins(
      Analise.arel_table.join(Empresa.arel_table).on(
        Empresa.arel_table[:id].eq(Dape.arel_table[:empresa_id])
      ).join_sources
    ).joins(
      Analise.arel_table.join(AreasAtuacao.arel_table).on(
        AreasAtuacao.arel_table[:id].eq(Empresa.arel_table[:area_atuacao_id])
      ).join_sources
    )
    

    【讨论】:

    • 我真的看不出它在做什么。 .joins(dape: [empresa: :area_atuacao]) 正在创建嵌套连接,实际上没有从 dapes 表或其上的任何条件中选择任何内容。我也相信.pluck 无论如何都会覆盖查询的选择子句。
    • 没有。 Pluck 覆盖 select 子句以返回单个列。 User.all.pluck(:name) =&gt; SELECT users.name FROM "users" =&gt; array。这就是重点 - 为单个列创建有效查询,而不是实例化一堆对象
    猜你喜欢
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多