How can I sort the results of Query using more than 1 property?
For example, I want to sort my Query results by 'lastname' and sort by 'firstname' in each group of 'lastname'.
Have you tried:
Person.all().order("lastname").order("firstname")
Just use two orders separated by comma, e.g.:
SELECT * FROM person ORDER BY lastname, firstname
See here for more details.
Related
$articles = Article::paginate(10, ['*'], 'pag');
What does the second parameter [*] above do?
The first parameters is the number of resources to be displayed by page.
The third parameter is the name of the query that will appear in the URL (i.e, "pag?=3").
What about "[*]"? I've used it for a long time without knowing what it does.
Don't tell me to search in Laravel Docs because I already did this and didn't find anything useful.
2nd parameter is select() method from Illuminate\Database\Eloquent\Builder which means select * from table ... limit 15.
You can specify which columns you want select from database.
For exaple $users->paginate(10, ['id', 'name']); -> select id, name from users ... limit 10
FYI: ['*'] is not fully qualified!
If you are using join in your select, it might be a problem if the columns with the same name are present in both tables. For example uuid, etc ...
In this case you should specify table name in select: ['table_name.*'] -> select table_name.* from table_name ... limit 15
I have a model User that has many Orders. Orders have many products, with the pivot table order-product. I don't want to preload and iterate through the orders if at all possible.
I need to return users where
signed_date === true on User
order_date on Order is after signed_date on User
order-product shows product hasn't been paid
I am failing on number 2.
In the following code, the first query within whereHas is wrong. I don't know how to reference the signed date of the user from within the where has. If I was iterating through users in a collection I could do something like ($query) use $user, but how do I do this without preloading all the users?
return User::whereNotNull('signed_date')
->whereHas('orders', function ($query) {
$query->where('order_date', '<=', 'user.signed_date');
$query->whereHas('products', function ($q) {
$q->where('paid', false);
});
})
->get(['id','fname','lname', 'title', 'signed_date']);
I would like to use eloquent if possible. If that is not possible, I would be happy for tips in solving this problem using the query builder/sql.
The Eloquent query builder has a special function called whereColumn('a', '<=', 'b') to compare columns instead of a column against a value. Using this function instead of a normal where() is necessary because of the way the query builder builds the actual query. You need to let the query builder know that you are going to pass a column name instead of a value for proper escaping and formatting of the query string.
Anyway, it seems you can also pass column names prefixed with a table name to the function, allowing you to compare columns across tables:
$query->whereColumn('orders.order_date', '<=', 'users.signed_date')
This works because you are using whereHas() in your query. Your query basically gets translated to:
SELECT id, fname, lname, title, signed_date
FROM users
WHERE signed_date NOT NULL
AND EXISTS (
SELECT 1
FROM orders
WHERE orders.order_date <= users.signed_date
AND EXISTS (
SELECT 1
FROM products
WHERE paid = 0
)
)
It might actually be not necessary at all to use the table name together with the column name in whereColumn(). But in case you'll ever add a column named the same on another table, the query might break - so IMHO it is good practice to use the table name in custom queries.
By the way, the reason this will not work together with with('relationship') is that this function results in an additional query and you obviously cannot compare columns across queries. Imagine the following:
Order::with('user')->take(5)->get();
It will be translated into the following:
SELECT *
FROM orders
LIMIT 5
SELECT *
FROM users
WHERE id IN (?, ?, ?, ?, ?)
where the five ? will be the user_ids of the orders. If the first query returns multiple rows with the same user_id, the amount of rows fetched from the users table gets reduced of course.
Note: All the queries are only examples. Might be that the query builder builds different queries based on the database type and/or escapes them differently (i.e. column names in backticks).
Let's say I have a bunch of job postings sorted by location.
How can I create a filter, to order the postings by filter, then show the rest below?
For instance, if I select New York, I want to see all NY job postings first, then show job postings in all other cities below the NY ones. Any way to do this?
Thanks!
You can also do something like this:
$selectedPostings = Posting::where('city', '=', 'New York')->get();
$otherPostings = Posting::whereNotIn('city', ['New York'])->get();
Try this
select * from table_name order by `location` regexp 'New York' desc;
In Rails 4, I have these 3 tables:
Users table with these columns:
-name
-email
Orders table with these columns:
-amount
-user_id
Items table with these columns:
-name
-description
OrderItems table with these columns:
order_id
item_id
Relations:
-The orderItems table is a joined table
-The user has many orders and an order belongs to a user.
Questions:
1) Find the 5 biggest orders (orders with the most items)
I think the query is:
OrderItem.group(:order_id).order(count(id) desc").limit(5).pluck(:order_id)
What is the group exactly doing? When I type in OrderItem.group(:order_id) only I Don't understand the output.
2) How do I find a user with the name "betty" AND "the email "betty#gmail.com". For this, do I need to write SQL inside my Arel?
OrderItem.group(:order_id) by itself won't produce valid SQL. group turns into an SQL GROUP BY statement which groups rows together if they share the same value for the column that is specified. GROUP BY needs to be used with a SELECT statement that has the columns that were in the GROUP BY or that are aggregate functions like COUNT.
Your full query is missing a quotation mark in the order clause. You'll want:
OrderItem.group(:order_id).order("count(id) desc").limit(5).pluck(:order_id)
To find a user with the name "betty" and the email "betty#gmail.com" you can use:
User.where(name: "betty", email: "betty#gmail.com")
I have user with name, location, created_at as important fields in table.
I want to retrieve for each user the latest location,i.e, I want something like this:
username location created_at
abc New York 2012-08-18 16:18:57
xyz Mexico city 2012-08-18 16:18:57
abc Atlanta 2012-08-11 16:18:57
only input is UId(1,2) array of userids.please help me to accomplish this.I just want to know how to write query using active record query interface.
Generally, this should be a standard way to solve this kind of problems:
SELECT l1.user, l1.location
FROM locations l1
LEFT JOIN locations l2 ON l1.user = l2.user AND l2.created_at > l1.created_at
WHERE l2.id IS NULL
The idea is to join the table with itself, and find those rows which don't have any row with the same user and greater created_at.
Of course, you should have (user, created_at) index on your table.
Now you should see how would that be represented in AR interface.
When
u_id
is the array of user ids, then
u_id.map{|i| User.find(i).location}
should be an array of the users locations.
You can Use
User.where(:uid => [1,2,3]).maximum('location')
which will create something like
SELECT MAX(`users`.`location`) AS max_id FROM `users` WHERE `users`.`id` IN (1, 2,3)