Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 原始SQL请求中的Rails 4字符串插值_Ruby On Rails_Ruby_Postgresql_Ruby On Rails 4 - Fatal编程技术网

Ruby on rails 原始SQL请求中的Rails 4字符串插值

Ruby on rails 原始SQL请求中的Rails 4字符串插值,ruby-on-rails,ruby,postgresql,ruby-on-rails-4,Ruby On Rails,Ruby,Postgresql,Ruby On Rails 4,在没有插值的情况下重写此查询的最佳方法是什么 def case_joins(type) subquery = <<-SQL.squish SELECT id FROM cases c2 WHERE c2.title_id = titles.id AND c2.value = 0 AND c2.type = '#{type}' ORDER BY c2.created_at DESC LIMIT 1 SQL "LEFT OUTER JOI

在没有插值的情况下重写此查询的最佳方法是什么

def case_joins(type)
  subquery = <<-SQL.squish
    SELECT id FROM cases c2
    WHERE c2.title_id = titles.id AND c2.value = 0 AND c2.type = '#{type}'
    ORDER BY c2.created_at DESC LIMIT 1       
  SQL
  "LEFT OUTER JOIN cases ON cases.title_id = titles.id AND cases.value = 0 AND cases.type = '#{type}' AND cases.id = (#{subquery})"
end

很难推断代码的其余部分是什么样子的,但我假设标题正在调用堆栈更上层的查询中使用

如果要使用ActiveRecord而不是本机SQL,可以执行以下操作:

def case_joins(scope, title_id, type)
  ids = Case.where(title_id: title_id, value: 0, type: type)
             .order('created_at desc').limit(1).pluck(:id)

  scope.joins('left outer join cases on cases.title_id = titles.id')
             .where(value: 0, type: type, id: ids)
end
这里的范围是您正在修改的当前AR查询

这是我不知道的,所以我不确定上面的AR语法是否正确,但它确实避免了插入SQL的需要,并且还使用了范围


不过,老实说,它的可读性并不比本机SQL强多少,所以。这至少意味着除了join之外,您没有在代码中编码SQL。

我假设您希望避免变量插值,这是危险的,因为它对SQL注入是开放的。我将简单地连接到从子查询中选择的案例,而不是将子查询放入WHERE条件。这确实涉及插值,但只涉及AR生成的SQL。我还将把它作为一个范围来实现,以利用AR范围链:

class Title < ActiveRecord::Base
  def self.case_joins(type)
    case_query = Case.from("cases c").where(c: {title_id: title_id, value: 0, type: type}).order('c.created_at DESC').limit(1)
    joins("LEFT OUTER JOIN (#{case_query.to_sql}) cases ON cases.title_id = titles.id")
  end
end

注意,删除了外部选择中多余的WHERE条件。

这里是对@eirikir答案的修改,其工作方式与所讨论的方法相同

def case_joins(type)
  case_query = Case.from("cases c").where('c.title_id = titles.id AND c.value = 0 AND c.type = ?', type).order('c.created_at DESC').select(:id).limit(1)
 "LEFT OUTER JOIN cases ON cases.title_id = titles.id AND cases.id = (#{case_query.to_sql})"
end

这看起来不错,但是我需要为子查询case\u query中的表指定一个不同的名称。我可以用WHERE来做这个吗?@Pav31我已经在子查询上用别名编辑了答案-你只需要使用from范围,然后编辑WHERE散列来匹配。谢谢!它起作用了,尽管我需要对你的方法做一些小改动,在limit1'之前添加select:id,并删除self',因为我在模型之外声明它。很好,如果它对你起作用,您可以继续并接受答案吗?如果您愿意使用.select:id而不是.pulk:id,那么到数据库服务器的往返只有一次,而不是两次;如果您有一个非常大的数据集,这可能是您唯一的选择。
def case_joins(type)
  case_query = Case.from("cases c").where('c.title_id = titles.id AND c.value = 0 AND c.type = ?', type).order('c.created_at DESC').select(:id).limit(1)
 "LEFT OUTER JOIN cases ON cases.title_id = titles.id AND cases.id = (#{case_query.to_sql})"
end