如何将此代码转换为原始 sql 并在 rails 中使用?因为当我在heroku中部署这段代码时,会出现请求超时错误。我认为如果我使用原始sql会更快。
@payments = PaymentDetail.joins(:project).order('payment_details.created_at desc')
@payment_errors = PaymentError.joins(:project).order('payment_errors.created_at desc')
@all_payments = (@payments + @payment_errors)
你可以这样做:
sql = "Select * from ... your sql query here"
records_array = ActiveRecord::Base.connection.execute(sql)
records_array
然后将是您可以迭代的数组中的 sql 查询的结果。
我知道这是旧的......但我今天遇到了同样的问题并找到了解决方案:
Model.find_by_sql
如果要实例化结果:
Client.find_by_sql("
SELECT * FROM clients
INNER JOIN orders ON clients.id = orders.client_id
ORDER BY clients.created_at desc
")
# => [<Client id: 1, first_name: "Lucas" >, <Client id: 2, first_name: "Jan">...]
Model.connection.select_all('sql').to_hash
如果您只想要一个值的哈希值:
Client.connection.select_all("SELECT first_name, created_at FROM clients
WHERE id = '1'").to_hash
# => [
{"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
{"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
]
结果对象:
select_all
返回一个 result
对象。你可以用它做一些神奇的事情。
result = Post.connection.select_all('SELECT id, title, body FROM posts')
# Get the column names of the result:
result.columns
# => ["id", "title", "body"]
# Get the record values of the result:
result.rows
# => [[1, "title_1", "body_1"],
[2, "title_2", "body_2"],
...
]
# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
{"id" => 2, "title" => "title_2", "body" => "body_2"},
...
]
# ActiveRecord::Result also includes Enumerable.
result.each do |row|
puts row['title'] + " " + row['body']
end
资料来源:
ActiveRecord - 通过 SQL 查找. Ruby on Rails - Active Record 结果。
#find_by_sql
正是我想要的,非常感谢。
您可以使用 ActiveRecord
执行原始查询。我会建议使用 SQL 块
query = <<-SQL
SELECT *
FROM payment_details
INNER JOIN projects
ON projects.id = payment_details.project_id
ORDER BY payment_details.created_at DESC
SQL
result = ActiveRecord::Base.connection.execute(query)
SELECT * FROM users WHERE users.id = #{ user.id }
您可以执行直接 SQL 以对两个表进行单个查询。我将提供一个经过清理的查询示例,以希望防止人们将变量直接放入字符串本身(SQL 注入危险),即使此示例未指定对它的需求:
@results = []
ActiveRecord::Base.connection.select_all(
ActiveRecord::Base.send(:sanitize_sql_array,
["... your SQL query goes here and ?, ?, ? are replaced...;", a, b, c])
).each do |record|
# instead of an array of hashes, you could put in a custom object with attributes
@results << {col_a_name: record["col_a_name"], col_b_name: record["col_b_name"], ...}
end
编辑:正如 Huy 所说,一个简单的方法是 ActiveRecord::Base.connection.execute("...")
。另一种方法是ActiveRecord::Base.connection.exec_query('...').rows
。并且您可以使用本机准备好的语句,例如,如果使用 postgres,可以使用 raw_connection、prepare 和 exec_prepared 完成准备好的语句,如 https://stackoverflow.com/a/13806512/178651 中所述
您还可以将原始 SQL 片段放入 ActiveRecord 关系查询中:http://guides.rubyonrails.org/active_record_querying.html 以及关联、范围等。您可以使用 ActiveRecord 关系查询构造相同的 SQL,并且可以使用 ARel 做一些很酷的事情,正如 Ernie 在 http://erniemiller.org/2010/03/28/advanced-activerecord-3-queries-with-arel/ 中提到的那样。而且,当然还有其他 ORM、gem 等。
如果这将被大量使用并且添加索引不会导致其他性能/资源问题,请考虑在数据库中为 payment_details.created_at 和 payment_errors.created_at 添加一个索引。
如果需要一次显示大量记录而不是所有记录,请考虑使用分页:
https://www.ruby-toolbox.com/categories/pagination
https://github.com/mislav/will_paginate
如果您需要分页,请考虑首先在数据库中创建一个名为 payment_records 的视图,该视图结合了 payment_details 和 payment_errors 表,然后为该视图创建一个模型(它将是只读的)。一些 DB 支持物化视图,这可能是提高性能的好主意。
还要考虑 Rails 服务器和 DB 服务器上的硬件或 VM 规格、配置、磁盘空间、网络速度/延迟/等、接近度等。如果没有,请考虑将 DB 放在与 Rails 应用程序不同的服务器/VM 上,等等.
我想使用 ActiveRecord
类的 exec_query
,因为它返回查询转换为对象的映射,因此当主题是原始 SQL 时,用对象迭代变得非常实用和高效。
例子:
values = ActiveRecord::Base.connection.exec_query("select * from clients")
p values
并返回这个完整的查询:
[{"id": 1, "name": "user 1"}, {"id": 2, "name": "user 2"}, {"id": 3, "name": "user 3"}]
仅获取值列表
p values.rows
[[1, "user 1"], [2, "user 2"], [3, "user 3"]]
仅获取字段列
p values.columns
["id", "name"]
您还可以将原始 SQL 与 ActiveRecord 条件混合使用,例如,如果您想在条件中调用函数:
my_instances = MyModel.where.not(attribute_a: nil) \
.where('crc32(attribute_b) = ?', slot) \
.select(:id)
records_array
将具有不同的类型。如果您使用 PG,它将是PG::Result
的实例,而不是Array
。PG::Result
对象上调用values
以获取结果数组ActiveRecord::Base.connection.exec_query
,因为它返回一个ActiveRecords::Result
对象,该对象具有方便的方法,如.columns
和.rows
来访问标题和值。来自.execute
的哈希数组可能很难处理,并且当我使用 SUM GROUP BY 子句运行时给了我多余的结果。