Пример Rails raw SQL
Как я могу преобразовать этот код в raw sql и использовать в rails? Потому что, когда я развертываю этот код в heroku, возникает ошибка тайм-аута запроса.Я думаю, что это будет быстрее, если я использую raw 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)
5 ответов
вы можете сделать это:
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
возвращает
вы можете сделать direct 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
редактировать: как сказал Хью, простой способ -ActiveRecord::Base.connection.execute("...")
. Другой способ -ActiveRecord::Base.connection.exec_query('...').rows
. И вы можете использовать собственные подготовленные операторы, например, если вы используете postgres, подготовленный оператор можно сделать с raw_connection, подготовка и exec_prepared как описано вhttps://stackoverflow.com/a/13806512/178651
вы также можете поместить необработанные фрагменты SQL в реляционные запросы ActiveRecord:http://guides.rubyonrails.org/active_record_querying.html и в ассоциациях, областях и т. д. Вероятно, вы могли бы построить тот же SQL с реляционными запросами ActiveRecord и можете делать классные вещи с ARel, как упоминает Эрни в http://erniemiller.org/2010/03/28/advanced-activerecord-3-queries-with-arel/. И, конечно, есть другие Ормы, драгоценные камни и т. д.
Если это будет использоваться много, и добавление индексов не вызовет других проблем с производительностью/ресурсами, рассмотрите возможность добавления индекса в БД для payment_details.created_at и payment_errors.created_at.
Если много записей и не все записи должны отображаться сразу, рассмотрите возможность использования разбиение на страницы:
Если вам нужно разбить на страницы, подумайте о создании представления в БД, которое сначала называется payment_records, которое объединяет таблицы payment_details и payment_errors, а затем имеет модель для представления (которая будет доступна только для чтения). Некоторые DBs поддерживают материализованные представления, что может быть хорошей идеей для спектакль.
также рассмотрите спецификации оборудования или VM на Rails server и DB server, config, дисковое пространство, скорость сети/задержка/и т. д. близость и т. д. И рассмотрите возможность размещения БД на другом сервере / виртуальной машине, чем приложение Rails, если у вас нет и т. д.
вы можете выполнить необработанный запрос, используя ActiveRecord
. И я предложу пойти с SQL block
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)
вы также можете смешивать необработанный SQL с условиями ActiveRecord, например, если вы хотите вызвать функцию в условии:
my_instances = MyModel.where.not(attribute_a: nil) \
.where('crc32(attribute_b) = ?', slot) \
.select(:id)