6

Ruby 1.9.2 / rails 3.1 / deploy onto heroku --> posgresql

Hi, Once a number of rows relating to an object goes over a certain amount, I wish to pull back every nth row instead. It's simply because the rows are used (in part) to display data for graphing, so once the number of rows returned goes above say 20, it's good to return every second one, and so forth.

This question seemed to point in the right direction: ActiveRecord Find - Skipping Records or Getting Every Nth Record

Doing a mod on row number makes sense, but using basically:

@widgetstats = self.widgetstats.find(:all,:conditions => 'MOD(ROW_NUMBER(),3) = 0 ')

doesn't work, it returns an error:

PGError: ERROR:  window function call requires an OVER clause

And any attempt to solve that with e.g. basing my OVER clause syntax on things I see in the answer on this question:

Row numbering in PostgreSQL

ends in syntax errors and I can't get a result.

Am I missing a more obvious way of efficiently returning every nth task or if I'm on the right track any pointers on the way to go? Obviously returning all the data and fixing it in rails afterwards is possible, but terribly inefficient.

Thank you!

2 Answers 2

8

I think you are looking for a query like this one:

SELECT * FROM (SELECT widgetstats.*, row_number() OVER () AS rownum FROM widgetstats ORDER BY id) stats WHERE mod(rownum,3) = 0

This is difficult to build using ActiveRecord, so you might be forced to do something like:

@widgetstats = self.widgetstats.find_by_sql(
  %{
    SELECT * FROM
    (
      SELECT widgetstats.*, row_number() OVER () AS rownum FROM widgetstats ORDER BY id
    ) AS stats
    WHERE mod(rownum,3) = 0
  }
)

You'll obviously want to change the ordering used and add any WHERE clauses or other modifications to suit your needs.

Sign up to request clarification or add additional context in comments.

Comments

2

Were I to solve this, I would either just write the SQL myself, like the SQL that you linked to. You can do this with

my_model.connection.execute('...')

or just get the id numbers and find by id

ids = (1..30).step(2)
my_model.where(id => ids)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.