4

I have two datetime columns in a User/users table: created_at and birthdate. I'd like to find users whose birthdate is less than 13 years before their creation date.

The equivalent Rails if statement would be ((created_at - birthdate) < 13.years)

How do I translate this to an ActiveRecord query (one that'll work on PostgreSQL)? Is this even possible, or will I have to iterate over all records manually?

2 Answers 2

12

The easiest way to do this is to use an interval, then it is pretty much a straight transliteration of the Rails version:

User.where(%q{created_at - birthdate < interval '13 years'})

The difference between two timestamps (or a timestamp and a date) is an interval so you just need the appropriate value on the right side of your comparison.

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

2 Comments

That works. Thank you! A note for anyone else reading this: interval doesn't work on SQLite. I had to log into my production server using PostgreSQL to test it out.
@LouieGeetoo: You really shouldn't be developing and deploying on different stacks, a little syntax difference with date arithmetic is going to be the least of your problems.
-1

You simply have to formulate that in PostgreSQL syntax inside your where clause.

For MySQL this would look similar to this using the datediff function:

User.where("DATEDIFF(created_at, birthdate) > (13 * 365)")

13*356 is there to represent 3 years in days since datediff returns difference in days.

I would then encapsulate that in a scope-like function like the following:

class User < ActiveRecord::Model
  def self.age_difference(years)
    where("DATEDIFF(created_at, birthdate) > (? * 365)", years)
  end
end

So you can call it:

User.age_difference(13).each do |user|
  puts user.inspect
end

I guess it's similar in Postgres.

5 Comments

You have a leap year problem.
Life is too short for leap year problems :D .. I just assumed it's not that much of an issue..
Leap years aside, it is generally accepted that there are 365 days in a year, not 356. ;) Thanks for the answer anyway.
@LouieGeetoo: It was generally accepted that two digits were enough to hold a year...
LouiGeetoo: Ups ;) yeah that happens when you have twenty things to do but hang out on stackoverflow instead..

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.