【问题标题】:named_scope + average is causing the table to be specified more then once in the sql query run on postgresqlnamed_scope + average 导致在 postgresql 上运行的 sql 查询中指定的表不止一次
【发布时间】:2010-05-15 07:55:23
【问题描述】:

我有一个这样的命名范围......

  named_scope :gender, lambda { |gender| { :joins => {:survey_session => :profile }, :conditions => { :survey_sessions => { :profiles => { :gender => gender } } } } }

当我调用它时,一切正常。

我也有这种我称之为普通的方法......

Answer.average(:rating, :include => {:survey_session => :profile}, :group => "profiles.career")

如果我这样称呼它也可以。

但是,如果我这样称呼它......

Answer.gender('m').average(:rating, :include => {:survey_session => :profile}, :group => "profiles.career")

我明白了……

ActiveRecord::StatementInvalid: PGError: ERROR: table name "profiles" 指定了多次 : SELECT avg("answers".rating) AS avg_rating,profiles.career AS profiles_career FROM "answers" 左外连接 "survey_sessions"survey_sessions_answers ON "survey_sessions_answers".id = "answers".survey_session_id 左外连接 "profiles" ON "profiles ".id = "survey_sessions_answers".profile_id INNER JOIN "survey_sessions" ON "survey_sessions".id = "answers".survey_session_id INNER JOIN "profiles" ON "profiles".id = "survey_sessions".profile_id WHERE ("profiles"."性别" = E'm') GROUP BY profiles.career

这有点难读,但说我包含了两次表格配置文件。

如果我只是从平均值中删除包含,它可以工作,但它并不实际,因为平均值实际上是在通过范围的方法内部调用的。因此,有时性别或平均水平可能会在没有对方的情况下被调用,如果其中任何一个缺少配置文件,则包含它将不起作用。

所以要么我需要知道如何在 Rails 中修复这个明显的错误,要么想办法知道哪些范围应用于 ActiveRecord::NamedScope::Scope 对象,以便我可以检查它们是否已被应用如果不添加平均值,则添加包含。

【问题讨论】:

  • 您是否尝试过将平均值的 :include 更改为 :joins?我发现如果 :joins 在不同的命名范围内是相同的,ActiveRecord 可以看到它们是相同的并且只执行一次。
  • Corey,最终成功了,奇怪的是 :include 和 :joins 不相互排斥。老实说,我想当我输入 sql sn-ps 时,我真的不需要 :include。

标签: ruby-on-rails postgresql activerecord named-scope


【解决方案1】:

看起来 ActiveRecord 正在生成一些错误的 SQL:

SELECT avg("answers".rating) AS avg_rating,
       profiles.career AS profiles_career
FROM "answers"
     LEFT OUTER JOIN "survey_sessions" survey_sessions_answers
                    ON "survey_sessions_answers".id = "answers".survey_session_id
     LEFT OUTER JOIN "profiles"
                     ON "profiles".id = "survey_sessions_answers".profile_id
     INNER JOIN "survey_sessions"
                ON "survey_sessions".id = "answers".survey_session_id
     INNER JOIN "profiles"
                ON "profiles".id = "survey_sessions".profile_id
WHERE ("profiles"."gender" = E'm')
GROUP BY profiles.career

大概它生成了左连接作为获取投影属性的一部分,而内部连接作为获取条件的一部分:如果它为这些表分配别名,这不会是无效的(只是效率低下),但它不会吨。有没有办法从您的应用中指定别名?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多