【问题标题】:Rails 4 - Join with AND clauseRails 4 - 加入 AND 子句
【发布时间】:2015-04-07 16:18:27
【问题描述】:

下面的查询会根据用户的下一个问题的状态为我提供该问题。它获取该特定部分的所有问题,然后范围对属于该用户的状态执行LEFT JOIN

我的问题是,这似乎不是一种非常 Railsy 的方法 - 是否有更好的方法来过滤我的表格,而不是这种笨拙的 AND.to_s 业务。我的问题是,显然,如果任何用户回答了该问题,那么左连接将填满该用户的答案,而我要求它为空。

基本上该查询有效,但很难看,我不知道这是否是最有效的方法!

scope :next_for_user, lambda { |user|
    joins("LEFT JOIN user_question_statuses ON user_question_statuses.question_id = questions.id AND user_question_statuses.user_id = ", user.id.to_s).
    reorder("user_question_statuses.answered ASC NULLS FIRST").
    order("user_question_statuses.updated_at ASC NULLS FIRST").
    limit(1)
  }

编辑:

我意识到这种方法特别容易受到 SQL 注入的影响,因此我将查询中的主行替换为:

joins(sanitize_sql_array(["LEFT JOIN user_question_statuses ON user_question_statuses.question_id = questions.id AND user_question_statuses.user_id = %d", user.id]))

这似乎有效并强制输入仅为整数。

编辑 2:

我的另一个选择是使用find_each 和用户first_or_create 为当前用户的特定问题部分创建空问题状态。这可能发生在他们需要他们寻找问题之前。这将允许我从问题到这些状态进行RIGHT JOIN,知道它们存在,但如果第一种方法有效且安全(并且尽可能 Railsy),那么没有理由改变它。

编辑 3:

我以这种方式构造了这个查询,因为 - 从 has_many questionssection 模型中 - 我想找到应该传递给 user 的下一个 question

要找到这个,我需要将所有user_question_statuses 加入到所有section 模型的问题中。可以做到这一点的唯一方法是question.id。但是,对于不同的用户,有许多带有该问题 ID 的 user_question_statuses。因此,在加入时,我需要 AND 子句在加入之前将 user_question_statuses 过滤到仅来自 user 的那些。一个用户,嘿,显然每个 question 只有一个状态。

我使用LEFT JOIN,因此如果状态尚不存在(它们仅在用户第一次尝试提问后创建)仍然存在NULLs 的状态,以便它们创建一行然后从中移动到顶部(因此NULLS FIRST)并可能服务器到user

这可能都非常不清楚!

【问题讨论】:

  • @muistooshort - 我已经更新了答案。希望解释是有道理的!

标签: ruby-on-rails postgresql join


【解决方案1】:

您所做的是跳过 Active Record 提供的 ORM 层并自己构建查询。您的感觉是正确的,这种方法有很多限制,并且不太适合 rails 所遵循的 MVC 模型。我建议通读 Active Record Query Interface 以了解以 rails/oop 方式进行操作的概念

【讨论】:

  • 我对查询界面很熟悉。但是,没有任何方法可以在 JOIN 上使用 AND 子句,尽管这需要我走出去。
猜你喜欢
  • 2012-08-16
  • 1970-01-01
  • 1970-01-01
  • 2013-12-23
  • 1970-01-01
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
  • 2015-08-26
相关资源
最近更新 更多