Rails select register from the previous day - sql

I'm trying to get the model instances with one day of history. I'm using postgreSQL.
What i want is likeness this:
element = Element.find(:first , :conditions => ["name LIKE ? AND created_at < ---ONE_DAY_CONDITION---)
What is the best way to solve it using a SQL query?
Thanks!

You mean 1.day.ago?
element = Element.find(:first,
:conditions => ["name LIKE ? AND created_at > ?", whatever, 1.day.ago])

Related

Rails simple sql comparison with another attribute

I think this should be quite simple. I want to do something like:
User.where("created_at < ?", :updated_at)
updated_at is another attribute of the User
Thanks in advance!
You can do the following:
john = User.where(username: 'john').first
users_updated_before_john = User.where('created_at < ?', john.updated_at)
After you commented:
I'm trying to do something like User.where("created_at < ?", Date.today - :updated_at) And I want the attribute created_at be compared with the updated_at for each user, not with the a static one.
Here is how you do it: (PostgreSQL 9.1 syntax!)
User.where('users.created_at::date < (users.updated_at::date - integer '5')')
The documentation about Date/Time functions in PostgreSQL (9.1):
http://www.postgresql.org/docs/9.1/static/functions-datetime.html

CakePHP SQL-query count

I have a problem concerning CakePHP SQL-queries. I need to fetch products from the database where shop_id is given and then count the products. All I need is Product.url and its count.
This will do the trick in plain SQL:
SELECT url,COUNT(*) as count FROM products GROUP BY url ORDER BY count DESC;
This one I used to get all products relating to shops:
$this->Product->find('all', array('conditions' => array('Product.shop_id'=>$id)));
That works correctly, but I need to convert that SQL-query above to CakePHP.
I tried something like this:
$this->Product->find('count', array('conditions' => array('Product.shop_id'=>$id),
'fields'=>array('Product.url','Product.id'),
'order'=>'count DESC',
'group'=>'Product.url'));
That returns only an int. But if I run that SLQ-query presented above in mysql server, I get two columns: url and count. How do I get the same results with CakePHP?
You can try this:
$data = $this->Post->query(
"SELECT COUNT(id),MONTH(created) FROM posts GROUP BY YEAR(created), MONTH(created);"
);
The most easiest way to do this:
$this->Product->query("SELECT url,COUNT(*) as count FROM products GROUP BY url ORDER BY count DESC;");
...at least for me.
Try the following code:
$this->Product->virtualFields['CNT_PRODUCTS'] = 0;
$this->Product->find('count', array('conditions' => array('Product.shop_id' => $id),
'fields' => array('Product.id', 'Product.url', 'count(*) as CNT_PRODUCTS'),
'order' => array('CNT_PRODUCTS' => 'DESC'),
'group' => 'Product.url'));

Complex SQL Query in Rails - User.where(hash)

My starting point is basically Ryan Bates Railscast.
I have User model that I need to do some queries on. The model has a couple hourly rate attributes as follows:
#User migration
...
t.decimal :hour_price_high
t.decimal :hour_price_low
...
I have the query working in the User.where(Array) format where Array is formatted
["users.hour_price_high <= ? OR users.hour_price_low >= ? OR users.hour_price_low <= ? AND users.hour_price_high >= ?", hour_price_high, hour_price_low, hour_price_low, hour_price_high]
#This is simply a search of two ranges. Search for $40/h - $60/h.
#It will return an User who charge any overlapping price range. Such as one who charges $45/h - $65/h, etc.
I simply wish to convert this into Ruby syntax in the where statement.
My problem is how to represent the OR.
#This isn't the full query shown above..
User.where(:high_price_high => hour_price_low..hour_price_high, :hour_price_low => hour_price_low..hour_price_high)
Produces this SQL:
=> "SELECT `users`.* FROM `users` WHERE (`users`.`hour_price_high` BETWEEN 45 AND 60) AND (`users`.`hour_price_low` BETWEEN 45 AND 60)"
Which, of course, is wrong because of the AND. I need it to be:
=> "SELECT `users`.* FROM `users` WHERE (`users`.`hour_price_high` BETWEEN 45 AND 60) OR (`users`.`hour_price_low` BETWEEN 45 AND 60)"
How can I make this be an OR statement without busting out the old truth table from my sophomore E.E. classes?
Thanks!
When you chain several where methods or have a few arguments in one where method, then you always get AND between them, so when you want to have OR you need to use this syntax:
User.where("users.hour_price_high <= ? OR users.hour_price_low >= ? OR users.hour_price_low <= ? AND users.hour_price_high >= ?", hour_price_high, hour_price_low, hour_price_low, hour_price_high)
Note: please watch http://railscasts.com/episodes/202-active-record-queries-in-rails-3 in order to get more information about active record queries.

RoR table join with "where" needed on both tables

I'm having trouble wrapping my head around joining tables. I have a one_to_many relationship between Locations and Listings. Locations have a longitude and latitude, as well as it's primary key: zipcode. Listings have a title and zipcode.
Listing.where("title LIKE ?", "%#{params[:search2]}%")
Location.where(:lat => #min_lat..#max_lat, :lon => #min_lon..#max_lon)
I'd basically Like to combine these two statements so that I can get all Listings within a given range of a zipcode, which is determnied by using a range of longitudes and latitudes. I can't figure out how to do this in Ruby on Rails in a fashion where I don't have to do separate SQL finds and loop through the data in my code to find the correct data.
Edit Updated code:
#results=Location.joins(:listings).where(:listings => ["title LIKE ?", "%#{params[:search2]}%"], :locations => {:zipcode => params[:searchZip]})
SQL output:SELECT "locations".* FROM "locations" INNER JOIN "listings" ON "listings"."location_id" = "locations"."zipcode" WHERE ("locations"."listings" IN ('title LIKE ?', '%fish%')) AND ("locations"."zipcode" = 44012)
I don't know why it is doing "locations"."listings" (which gives an error), or where the IN is coming from.
I suggest using ARel as opposed to writing your own SQL:
Listing.joins(:location).
where(:listings => {:lat => #min_lat..#max_lat, :lon => #min_lon..#max_lon},
:location => ["title LIKE ?", "%#{params[:search2]}%"])
If I am understanding correctly that Location has_many :listings, then this query will return all of the listings in the location range with matching titles:
Listing.joins(:location).where(
'listings.title LIKE ? AND
locations.lat BETWEEN ? AND ? AND
locations.lon BETWEEN ? AND ?',
"%#{params[:search2]}%", #min_lat, #max_lat, #min_lon, #max_lon)
Location.joins(:listings).where(:listings => {:lat => #min_lat..#max_lat, :lon => #min_lon..#max_lon} )

Rails SQL Query with find

I want this SQL query to be written in rails controller using find:
select id,name from questions
where id not in (select question_id from levels_questions where level_id=15)
How will I do this? I am using Rails framework and MySQL.
Thanks in advance.
Question.find_all_by_sql('select id,name from questions where id not in (select question_id from levels_questions where level_id=15)')
This is admittedly non-ActiveRecord-ish, but I find that complicated queries such as this tend to be LESS clear/efficient when using the AR macros. If you already have the SQL constructed, you might as well use it.
Some suggestions: encapsulate this find call in a method INSIDE the Question class to hide the details from the controller/view, and consider other SQL constructions that may be more efficient (eg, an OUTER JOIN where levels_questions.question_id is null)
Simple way:
ids = LevelsQuestion.all(:select => "question_id",
:conditions => "level_id = 15").collect(&:question_id)
Question.all(:select => "id, name", :conditions => ["id not in (?)", ids])
One shot:
Question.all(:select => "id, name",
:conditions => ["id not in (select question_id from levels_questions where level_id=15)"])
And the rails 3 way:
ids = LevelsQuestion.select(:question_id).where(:level_id => 15).collect(&:question_id)
Question.select(:id, :name).where("id not in (?)", ids)