Eloquent: Order by sum of two columns - laravel

My working SQL query is as follows:
SELECT post_id
FROM news_tags
ORDER BY (link_clicks+views) DESC
What I've tried so far in eloquent is like this:
$newsTagSaved = NewsTag::
orderBy(DB::raw("`views` + `link_clicks`"), 'desc')
->paginate(12)
->pluck('post_id');
Newstag table has many columns and views and link_clicks are two of them. Now, I'm trying to retrieve the post_id order by desc of sum of views and link_click.
How can I do it in Laravel eloquent?
Thank you!

Do something like this:
$newsTagSaved = NewsTag::select(DB::raw('views + link_clicks as score'))
->orderBy('score', 'desc')
->get();
dd($newsTagSaved);
This will return just score value. If you want to return other fields, simply add them to select. As an example:
$newsTagSaved = NewsTag::select(
DB::raw('views + link_clicks as score'),
'title',
'created_at'
)
->orderBy('score', 'desc')
->get();
dd($newsTagSaved);

Related

Convert DB::Select to Query Builder

i has raw query in laravel like this
public function getPopularBook(){
$book = DB::select("
with totalReview as(
SELECT r.book_id , count(r.id)
FROM review r
GROUP BY r.book_id
)
SELECT *
from totalReview x
left JOIN (
SELECT b.*,
case when ((now() >= d.discount_start_date and now() <= d.discount_end_date) or (now() >= d.discount_start_date and d.discount_end_date is null)) then (b.book_price-d.discount_price)
ELSE b.book_price
end as final_price
FROM discount d
right JOIN book b
on d.book_id = b.id
) as y
on x.book_id = y.id
ORDER BY x.count DESC, y.final_price ASC
LIMIT 8"
);
return $book;
}
so when i want to return a paginate, it doesn't work so can i convert this to query build to use paginate
This is a very un-optimized raw query in itself. You are performing too many Join in Subquery just to sort by price
i'm assuming the database table:
books[ id, name, price ]
reviews[ id, book_id ]
discounts[ id, book_id, start_date, end_date, discount_price]
Look how easy it is if you just use Eloquent:
Book::withCount('reviews')->orderBy('reviews_count')->get();
this will give you all the Books order by number of reviews
now with the final price, this can be a bit tricky, let's take a look at a query when we don't consider discount time
Book::withCount('reviews')
->withSum('discounts', 'discount_price') //i'm assuming a book can have many discount at the same time, so i just sum them all
->addSelect(
DB::raw('final_price AS (books.price - discounts_sum_discount_price)')
)
->orderBy('reviews_count', 'asc') // =you can specify ascending or descending
->orderBy('final_price', 'desc') //in laravel chaining multiple orderBy to order multiple column
->get();
I dont even need to use Subquery!! But how do we actually only add the "active" discount?, just need to modify the withSum a bit:
Book::withCount('reviews')
->withSum(
[
'discounts' => function($query) {
$query->where('start_date', '<=', Carbon::now())
->where('end_date', '>=', Carbon::now())
}
],
'discount_price'
)
->addSelect(
DB::raw('final_price AS (books.price - discounts_sum_discount_price)')
)
->orderBy('reviews_count', 'asc') // =you can specify ascending or descending
->orderBy('final_price', 'desc') //in laravel chaining multiple orderBy to order multiple column
->get();
and it is done
What about pagination? just replace the get() method with paginate():
Book::withCount('reviews')
->withSum(['discounts' => function($query) {
$query->where('start_date', '<=', Carbon::now())->where('end_date', '>=', Carbon::now())
}],'discount_price')
->addSelect(DB::raw('final_price AS (books.price - discounts_sum_discount_price)')) //just format to be a bit cleaner, nothing had changed
->orderBy('reviews_count', 'asc')
->orderBy('final_price', 'desc')
->paginate(10); //10 books per page
WARNING: this is written with ELoquent ORM, not QueryBuilder, so you must define your relationship first

How to merge count and sum queries in one query in Eloquent

I have problem with queries in my Controller. I want to count rows and sum by column in one query.
Relations view
So far, I created two queries:
Query to count rows
$paymentsCount = Payments::where('pay_status', 'like', "%{$payStatus}%")->count();
Query to sum
$paymentsValue = Payments::where('pay_status', 'like', "%{$payStatus}%")->sum('brutto');
I have no Idea, how to make on query instead this two queries.
I will be grateful for any help.
The query builder allows you to customize your SELECT clause with the select() method.
Use it to add COUNT() and SUM() in addition of the other columns:
$payments = Payments::select('*', 'COUNT(*) AS count', 'SUM(brutto) AS sum')
->where('pay_status', 'LIKE', "%{$payStatus}%")
->get();

how to retrieve multiple table data with multiple criteria in laravel eloquent?

I want to retrieve data from 4 different table using laravel eloquent with multiple criteria.
an Overview of my table;
table 1
id
name
table 2
id
name
year
table1_id
table 3
id
name
description
table2_id
table 4
id
name
quarter
table3_id
below are their relations
table 1
hasMany -> table 2
table 2
belongsTo ->table1
HasMany->table2
table 3
belongsTo ->table2
HasMany->table3
table 4
belongsTo ->table3
I'd like to fetch the data by resource show with two parameters
and i tried this
$Report = Table1::whereHas('tabke1', function($query){
$query->where('year', 'like','%'.$year.'%');
})
->with('table2')->whereHas('table3', function($query){
$query->where('quarter', 'like', '%'.$quarters.'%');
})
->get();
but im receiving syntax error.
How can I retrieve the data from multiple table with multiple filter?
i tried this table query to understand more what i expect
SELECT `table1`.*, `table2`.*, `table3`.*, `table4`.*
FROM `table1`, `table2`, `table3`, `table4`
WHERE ((`table2`.* year = 2019) AND (`table4`.* quarter = 1))
I reckon there are two queries to achieve the results.
The first query is something like:
Table1::whereHas('table2', function ($query) {
$query->where('year', 2019);
})
->whereHas('table2.table3.table4', function ($query) {
$query->where('quarter', 1);
})
->get();
The second query is something like:
Table1::select('table1.*')
->join('table2', 'table1.id', '=', 'table2.table1_id')
->join('table3', 'table2.id', '=', 'table3.table2_id')
->join('table4', 'table3.id', '=', 'table4.table3_id')
->where('table2.year', 2019)
->where('table4.quarter', 1)
->distinct()
->get();
Regarding performance, I prefer the second query.

Wherein query to related tables

I have been trying to a query where in I want to do some validation on the related tables. I would like to do something like this using Laravel 5
select
*
from
table1
INNER JOIN table3 on(table1.id = table3.table1_id)
INNER JOIN table2 on(table1.id = table2.table1_id)
where
table2.column2 in ('arr1', 'arr2');
Also table1 is related to 5 - 7 tables and I want to eager load all of this. Here's what I had so far
$reports = Table1::with(
[
'table3',
'table4',
'table5.table6',
'table7',
'table8',
])
->where('created_at', '>=', date('Y-m-d', strtotime($request->get('from'))))
->where('created_at', '<', date('Y-m-d', strtotime($request->get('to'))))
->with('table2',function($query) use($table1_column){
return $query->whereIn('table1_column',$table1_column);
});
But this displays everything. Even the items that does not exist in table2. What I would like to achieve is to create a result where all items is the only items that exists in table2. Meaning all transaction made using items in table2.
Assuming the item in table2 has an ids of 123, 456, and 789 then I would like to display all record related to this id's
How can I make this kind of result
You can use the whereHas method.
$reports = Table1::with(
[
'table3',
'table4',
'table5.table6',
'table7',
'table8',
])
->whereHas('table2', function($query) use($table1_column){
return $query->whereIn('table1_column',$table1_column);
})
->where('created_at', '>=', date('Y-m-d', strtotime($request->get('from'))))
->where('created_at', '<', date('Y-m-d', strtotime($request->get('to'))));
Note that this does not include the table 2 data in the result set. If you need that include the table2 relation name in the with method call.

subquery with distinct clause in query builder/laravel

SELECT * FROM `movie_list`
WHERE `movie_id` IN
(SELECT DISTINCT movie_id FROM `movie_genre` where genre_id in (12,18,53))
AND rated IN
('Not Rated','N/A')
How can i convert the above to a query builder syntax:
$movies = DB::table('movie_list')
->whereIn('movie_id',function($query){
$query->select.....
})->get();
I have the inner one: it goes like this:
DB::table('movie_genre')
->whereIn('genre_id', array(12,18,53))
->distinct()
->get(array('movie_id'));
How do i use this result with the rest of my query?
You could do this alot smoother with Eloquent Models, but assuming you don't have your models setup, this should do the trick (untested)
$ids = DB::table('movie_genre')
->whereIn('genre_id', [12,18,33])
->distinct()
->get(['movie_id'])
->toArray();
$movies = DB::table('movie_list')
->whereIn('movie_id', array_values($ids))
->get();

Resources