Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord: Select max of limit

I'm trying to convert the following SQL query to ActiveRecord and it's melting my brain.

delete from table where id <= (
select max(id) from (
    select id from table order by id limit 0, 10));

Any ideas?

What I'm trying to do is limit the number of rows in the table. So, I want to delete anything that is less than the most recent 10 entries.

edit: Found a solution by combining several of the below answers.

Temperature.where('id < ?', Temperature.order('id DESC').limit(10).pluck(:id).min).destroy_all

This leaves me with the latest 10 entries.

like image 847
LifeOfRPi Avatar asked Aug 21 '13 20:08

LifeOfRPi


People also ask

What is eager loading in rails?

Eager loading is a way to find objects of a certain class and a number of named associations. Here I share my thoughts on using it with Rails. What are N + 1 queries? It mainly occurs when you load the bunch of objects and then for each object you make one more query to find associated object.

What is Active Record Ruby?

What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.

What is include in Rails?

Rails provides an ActiveRecord method called :includes which loads associated records in advance and limits the number of SQL queries made to the database. This technique is known as "eager loading" and in many cases will improve performance by a significant amount.


3 Answers

From your SQL, it looks like you want to delete the first 10 records from the table. I believe most of the answers so far will so that. Here are two additional alternatives:

Based on MurifoX's version:

Table.where(:id=>Table.order(:id).limit(10).pluck(:id)).destroy_all

This will effectively perform a WHERE id IN (...)

Slightly shorter version:

Table.order(:id).limit(10).destroy_all

This will simply grab the first 10 records and destroy

EDIT: To grab all but the most recent X number of records (10 for example), only way I can think of to do that at the moment is this:

 Table.order(:id).limit(Table.count - 10).destroy_all if Table.count > 10

In essence, grab the oldest records, leaving only the 10 most recent, and destroy them, assuming the table size is greater than 10. Maybe there's a cleaner way to do it, but that's the only way I can imagine doing this right now.

like image 72
Paul Richter Avatar answered Sep 20 '22 03:09

Paul Richter


model = Model.order(:id).limit(10).last

Model.where("id <= ?", model.id).destroy_all
like image 38
Zippie Avatar answered Sep 17 '22 03:09

Zippie


Hmm, maybe this?

Model.destroy(Model.where('id <= ?', Model.order(:id).limit(10).pluck(:id).max))
like image 32
MurifoX Avatar answered Sep 20 '22 03:09

MurifoX