I want to generate the following SQL query using ActiveRecord for Rails:
SELECT * FROM users WHERE (((1 IS NULL) OR (10 > 20)) AND (2 IS NULL OR (10 > 1)));
So I wrote the following scope:
where('1 IS NULL')
.or(where('10 > 20'))
.where('2 IS NULL')
.or(where('10 > 1'))
However I am getting a slightly different query:
SELECT * FROM users WHERE (((1 IS NULL) OR (10 > 20)) AND 2 IS NULL OR (10 > 1));
Note that the first has no brackets surrounding everything after AND
whilst the first does. This effects the results I get (the first query evaluates to false whilst the second true).
How can I write the second query using ActiveRecord?
This question seems very similar: How to properly add brackets to SQL queries with 'or' and 'and' clauses by using Arel? Arel is now part of Rails so any answer there should be relevant.
The difference is both queries are the same which lead to a discussion about how to make it clearer, and secondly it was for an older version of Rails so the answers don't seem to work.
I also don't want to need a new gem for this, I think ActiveRecord should be able to handle this.
Edit:
I ended up writing it like this:
where("(1 IS NULL OR 10 > 20) AND (2 IS NULL OR 10 > 1)")
but now I'm just going around ActiveRecord, I was hoping to do it with ActiveRecord
SQL: Using Parentheses with And / OR condition is necessary with where clause to gives expected result.
Eager loading lets you preload the associated data (authors) for all the posts from the database, improves the overall performance by reducing the number of queries, and provides you with the data that you want to display in your views, but the only catch here is which one to use. Gotcha!
How lazy loading works: Whenever you try to get some data from database, For example, users is the database table that you have. And you are querying database to get users having age less than 20.
Whereas an instance of ActiveRecord::Relation is a representation of a query that can be run against your database (but wasn't run yet). Once you run that query by calling to_a , each , first etc. on that Relation a single instance or an array of ActiveRecord::Base instances will be returned.
You can get something similar, just without the main parentheses wrapping the where clause conditions:
User.where('foo IS NULL')
.or(User.where('10 > 20'))
.merge(User.where(bar: nil).or(User.where('10 > 1')))
# SELECT "users".*
# FROM "users"
# WHERE ((foo IS NULL) OR (10 > 20)) AND ("users"."bar" IS NULL OR (10 > 1))
Consider foo
equals 1
and bar
equals 2
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With