How to convert this into an active record query?
select quantity from carts where cart_id = ? and product_id = ?
Cart.select(:quantity).where(:cart_id => cart_id, :product_id => product_id)
If you're interested only in the value, and not the overhead of the object (so you're not interested in any of the Cart methods, associations etc), then pluck is available and a little better performing:
Cart.pluck(:quantity).where(:cart_id => cart_id, :product_id => product_id)
Related
In an ecommerce shop application I would like to retrieve all orders that match a first_name that was entered via a search form and where paid == true. The search form submits the search term via params Parameters: {"utf8"=>"✓", "search"=>"john", "commit"=>"Search"}. In the controller
#users = User.search(params[:search]) #returns all users with the matching first_name, e.g. 'john'
#order = Order.where('user_id = ? AND paid = ?', #users.ids, true )
The query in #order works just fine, if only one user is returned, e.g. only one user is named john. But if multiple users are named John, multiple user ids are returned and the error message ActiveRecord::StatementInvalid is returned. My understanding is that the query stops working once `#users.ids is an array with more than one value.
How do I structure the following query: for each user_id return all orders (user.orders) where paid equals true.
Models
user.rb
has_many :orders
order.rb
belongs_to :users
There are various ways to go about this.
You can use a JOIN as Nic Nilov suggests but this can be difficult if your #users query is built using scopes and you don't want to manually inline those scopes.
You could also use a subquery since ActiveRecord in Rails4 is smart enough do The Right Thing when you use a relation in a where, you just have to use the hash form of where:
#users = User.search(params[:search])
# #users should be a User::ActiveRecord_Relation now.
#orders = Order.where(:user_id => #users, :paid => true)
This will end up with SQL like:
select *
from orders
where paid = 't'
and user_id in (
select id
from users
where /* whatever `search` does... */
)
The advantage here is that you don't need to know what User.search does as long as it is returning an ActiveRecord relation.
If your #users is actually an array (of ids or whole User instances) then you'd do it exactly the same way:
# Suppose #users is an array of Users or an array of User ids...
#orders = Order.where(:user_id => #users, :paid => true)
and ActiveRecord will figure out what to do with your #users array without you having to do anything extra.
Instead of two queries, you should use a nested query with a WHERE IN clause
SELECT * from Order WHERE user_id IN (SELECT user_id FROM users WHERE first_name LIKE ?) AND paid = true
This should do:
Order.joins(:user).where(users: { name: params[:search] }, paid: true)
It generates a single query with an INNER JOIN:
SELECT "orders".*
FROM "orders"
INNER JOIN "users" ON "users"."id" = "orders"."user_id"
WHERE "users"."name" = 'Test User' AND "orders"."paid" = 't'
I wrote a joint query using NHiberNate, but I am getting a NHibernate.QueryException:not an association: Id
This is what it looks like with NHibernate library
TicketRequest ticketAlias = null;
Show showAlias = null;
IList<TicketRequest> results = UnitOfWork.CurrentSession.QueryOver<TicketRequest>(() => ticketAlias)
.JoinAlias(() => ticketAlias.ShowId, () => showAlias.Id)
.Where(() => showAlias.ShowDate >=DateTime.Now)
.List();
return results;
I just want a simple joint statement, and this is what it would have been in SQL
select * from TicketRequest as a join Show as b
on a.Show_id = b.Id
where ShowDate >=GETDATE()
Can someone help and let me know why I am getting a "not an association:Id" error. I have id in the "Show" table, it is a primary key.
Please advise. All helps are greatly appreciated.
You need to specify a many-to-one relation in joins. In your case that is the Show property.
IList<TicketRequest> results = UnitOfWork.CurrentSession.QueryOver<TicketRequest>(() => ticketAlias)
.JoinAlias(() => ticketAlias.Show, () => showAlias)
.Where(() => showAlias.ShowDate >= DateTime.Now)
.List();
PS: You shouldn't map both a many-to-one relation (Show) and an foreign key property (ShowID). Usually you only work with object relations when using an ORM. Only map the plain ID if you really need it for something, but even then only map it as read-only.
You don't have to specify the foreign keys / primary keys when querying with NHibernate. It's an ORM. You write object oriented queries. The keys and relations are specified in the mapping file.
A Join in an NHibernate query is simply specified by the property name with which you navigate to the other property.
That's what the error message means. Id is not an association.
I am trying to get my users (authors actually, there will be maximum of 5-6 authors) with their one last post to show in a sidebar in the homepage. Since they will be listed in the homepage I am trying to reduce the amount of sql queries due to performance issues. I have tried;
$users=User::with(array('posts'=>function($query){
$query->take(1);
}))->get();
However it gets only one post in total, not one for every user. And my sql knowledge is limited.
How can I solve my poblem using Eloquent ORM, Query Builder or raw sql query?
A solution is to define a hasOne relationship on the User model ordering by the posts created_at column.
public function lastPost()
{
return $this->hasOne('Post')->orderBy('created_at', 'desc');
}
Then your query would be as such.
$users = User::with('lastPost')->get();
To limit the columns you can constrain the query either at the relationship level:
return $this->hasOne('Post')->select('id', 'user_id', 'title', 'created_at')->orderBy('created_at', 'desc');
Or when you use the with method:
$users = User::with(['lastPost' => function($query)
{
$query->select('id', 'user_id', 'title', 'created_at');
})->get();
Note that you need the user_id and created_at columns as well, as they're required for the WHERE and ORDER BY clauses in the query.
The general SQL way to do this is:
select p.*
from posts p join
(select p.authorid, max(created_at) as maxdate
from posts p
group by p.authorid
) psum
on p.authorid = psum.authorid and p.created_at = psum.maxdate
This assumes that there is are no duplicates.
Depending on the database you are using, there are definitely other ways to write this query. That version is standard SQL.
Suppose say I have Order, Items, OrderItems tables with Order and Items having n:n relationship and OrderItems being associative table. I have seen below two approaches for defining them.
1.Create Order and Items entities with "HasMany" relationship with OrderItems.
2.Create Order, Items and OrderItems entities with Order and Items having "ManytoMany" relationship and "OrderItems" containing Order and Item properties.
I have approach 1 which works fine but would like to know what approach 2 does.
If the relationship between Items and Orders is simple (merely that the relationship exists), then you would do a ManyToMany mapping between Items.Orders and Orders.Items. This would result in NHibernate generating and managing a simple cross reference table containing the two foreign keys.
On the other hand, if there is additional information that you need to record along with the two foreign keys, you must use a distinct entity or value object to capture that information, using HasMany on both sides.
Classes:
Order
Id
Name
OrderItems
Item
Id
Name
OrderItems
OrderItem
Id
Order
Item
Quantity
Mappings:
Order:
Id(c => c.Id);
Map(c => c.Name);
HasMany(c => c.OrderItems).KeyColumn("OrderId");
Item:
Id(c = c.Id);
Map(c => c.Name);
HasMany(c => c.OrderItems).KeyColumn("ItemId");
OrderItem:
Id(c => c.Id);
Map(c => c.Quantity);
References(c => c.Order);
References(c => c.Item);
I have 3 tables
task (Id,text,Contact_Id)
users(Id,name)
company(id,name)
and 2 junction tables
task_users (task_id,user_id)
task_companies (task_id,company_id)
note: contact_id may be refer to users table or company
How can I get task id, task text, contact name in one Criteria
This's example with QueryOver, but it almost like ICriteria.
Contact contact = null;
mappingSession.QueryOver<Task>()
.JoinAlias(() => task.Contact, () => contact)
.SelectList(list => list
.SelectGroup(task => task.Id)
.Select(task => task.Text)
.Select(() => contact.Name))
.TransformUsing(Transformers.DistinctRootEntity)
.List();
Other is a mapping. You can make base entity "Contact" and extend from it User and Company.