How to convert mysql query to laravel query builder? - mysql

I have 2 tables and in first comments and article id, in second article title, id , category of article. I want has a title of article which has the most comments.
SELECT comments.article_id, news.title, news.category_id,
COUNT(comments.id) as counts
FROM comments
JOIN news ON news.id = comments.article_id
GROUP BY(article_id)
ORDER BY counts DESC
LIMIT 3
I tried this:
$articles = DB::table('comments')
->join('news', 'news.id', '=', ' comments.article_id')
->select(comments.article_id', 'news.title', ' news.category_id')
->count('comments.id')
->groupBy('article_id')
->orderBy(DB::raw('count(comments.id)', 'desc')
->limit(3)
->get();
But had:
Call to a member function groupBy() on integer

You are using a "finisher", which means ->count('comments.id') does not return an instance of QueryBuilder anymore but a regular type (integer).
As integers in PHP are not classes, you are trying to perform a method on an non-class, which led to display this error message.
You surely know others finishers like ->sum(), ->all(), ->get(), ...
Just remove your line ->count('comments.id') and you will be good to go:
$articles = DB::table('comments')
->join('news', 'news.id', '=', ' comments.article_id')
->select('comments.article_id', 'news.title', ' news.category_id')
->groupBy('article_id')
->orderBy(DB::raw('count(comments.id)', 'desc')
->limit(3)
->get();

DB::table('comments')
->join('news', 'news.id', '=', ' comments.article_id')
->selectRaw('comments.article_id', 'news.title', ' news.category_id', 'count(comments.id) as countsxyz')
->groupBy('article_id')
->orderBy(DB::raw('countsxyz'), 'desc')
->limit(3)
->get();
try this and let me know if you still face any issue.

Related

Convert Raw SQL query to Laravel DB Query

I have the following raw SQL query:
select a.id user_id, a.email_address, a.name_first, a.name_last, count(b.id) number_of_videos, sum(b.vimeo_duration) total_duration, sum(b.count_watched) total_playbacks
from users a,
videos b
where a.id = b.tutor_id
and a.email_address in ('candace_rennie#yahoo.com', 'tjm#hiltoncollege.com', 'matthewjameshenshall#gmail.com', 'nkululeko#syafunda.co.za', 'khulile#syafunda.co.za', 'nzakheni#syafunda.co.za')
group by a.id;
This correctly gets 6 rows from the database. I'm trying to convert this to a Laravel database query like so:
$totals = DB::table('users')
->select(DB::Raw('users.id as user_id'), 'users.email_address', 'users.name_first', 'users.name_last', DB::Raw('count(videos.id) as number_of_videos'), DB::Raw('sum(videos.vimeo_duration) as total_duration'), DB::Raw('sum(videos.count_watched) as total_playbacks'))
->join('videos', 'users.id', '=', 'videos.tutor_id')
->where('users.id', 'videos.tutor_id')
->whereIn('users.email_address', array('candace_rennie#yahoo.com', 'tjm#hiltoncollege.com', 'matthewjameshenshall#gmail.com', 'nkululeko#syafunda.co.za', 'khulile#syafunda.co.za', 'nzakheni#syafunda.co.za'))
->groupBy('users.id')
->get();
This however return 0 rows. Is there anything I'm missing?
It should be smth like below even tho groupBy user id does not help much as id is unique.
$aggregates = [
DB::raw('count(b.id) as number_of_videos'),
DB::raw('sum(b.vimeo_duration) as total_duration'),
DB::raw('sum(b.count_watched) as total_playbacks'),
];
$simpleSelects = ['users.email_address', users.id, 'users.name_first', 'users.name_last'];
$emails = ['candace_rennie#yahoo.com', 'tjm#hiltoncollege.com'....]
$users = Users::select(array_merge($simpleSelects, $aggregates))
->leftJoin('videos as b', function ($join) use ($emails) {
$join->on('b.tutor_id', 'a.id')
->whereIn('users.email_address', $emails);
})
->groupBy('users.id')
->get();
Try to remove this line:
->where('users.id', 'videos.tutor_id')
List item
after sql code convert into laravel
DB::select('posts.id','posts.title','posts.body')
->from('posts')
->where('posts.author_id', '=', 1)
->orderBy('posts.published_at', 'DESC')
->limit(10)
->get();

Join 3 table with query builder in laravel

I have a 3 table questions,registrations,ssi_tracks i need to get details from the registraions table by corresponding to other two tables
i need to get details from registrations based on
questions.question_schedul=0 ,ssi_tracks.track_first_status
i have wrote query but it says the column is not found here is my query
$register = DB::table('registrations')
->join('questions', 'registrations.registration_id', '=', 'questions.question_id')
->join('ssi_tracks','registrations.registration_id','=','ssi_tracks.registration_id')
->select('address', 'model', 'chassis', 'delivery_date','ssi_tracks.track_first_status')
->where([["questions.question_schedul", "=", $dropselected] and ['ssi_tracks.track_first_status',0]])
->get();
Try this:
$register = DB::table('registrations as R')
->select('R.address', 'R.model', 'R.chassis', 'R.delivery_date','S.track_first_status')
->join('questions as Q', 'R.registration_id', '=', 'Q.question_id')
->join('ssi_tracks as S','R.registration_id','=','S.registration_id')
->where('Q.question_schedul', '=', $dropselected)
->where('S.track_first_status', '=', 0)
->get();
Make sure you have used the right column here from question table for matching registration id:
->join('questions as Q', 'R.registration_id', '=', 'Q.question_id')
try this query :
$register = DB::table('registrations')
->leftJoin('questions', 'registrations.registration_id', '=', 'questions.question_id')
->leftJoin('ssi_tracks','registrations.registration_id','=','ssi_tracks.registration_id')
->select('registrations.address', 'registrations.model', 'registrations.chassis', 'registrations.delivery_date','ssi_tracks.track_first_status')
->where(['questions.question_schedul'=>$dropselected,'ssi_tracks.track_first_status'=>0])
->get();

WhereNotIn Subquery

What i'm trying to achieve is the following:
I want to check if there is a record with the same client_code but with a lower/different campaign id. I'm using a sub-query for now and i tried to do it with a join as well but I couldn't get the logic working
This is what i got now:
$oDB = DB::table('campaigns AS c')
->select(
'c.id AS campaign_id',
'cc.id AS campaign_customer_id'
)
->join('campaign_customers AS cc', 'cc.campaign_id', '=', 'c.id')
->where('c.status', '=', ModelCampaign::STATUS_PLANNED)
->where('c.scheduled', '=', 1)
->whereRaw('c.scheduled_at <= NOW()')
->where('cc.status', '=', ModelCampaignCustomer::STATUS_INVITE_EMAIL_SCHEDULED)
->whereNotIn('cc.client_code', '=', function ($query){
$query ->select(DB::raw(1))
->from('campaign_customers')
->whereRaw('campaign_id', '!=', 'c.id');
})
->where('cc.active', '=', 1)
;
any tips on how to work the logic would be great
You can use the ->toSql(); method to see the SQL so you can refactorize your query.
The whereNotIn probably shouldn't have an = in it
->whereNotIn('cc.client_code', function ($query){
....
edit
Try:
->whereNotIn('cc.client_code', function ($query){
$query->select(DB::raw('client_code'))
->from('campaign_customers')
->whereRaw('campaign_id != c.id');
})
I think the whereRaw should be a single text string or maybe you can use where here (looking at this for reference https://laravel.com/docs/5.2/queries#advanced-where-clauses). Also DB::raw(1) is going to return a 1 for each subquery result but you want an id for the whereNotIn.

Which laravel query to use to sort top entries according to related table

I have two models: posts and likes. Posts and likes have one-to-many relationship (so, one post has many likes). Likes model has also an isActive field which shows liking is active or passive.
I want to get (sort) top 5 posts which had received maximum "active" likes (only likes whose isActive field is true would be considered).
Which Laravel query could give me the result?
My question is sorting the post not only according to a field of a related model but also count of entries in the related table.
This is the query:
$posts = Post::selectRaw('posts.*, count(likings.id) as likes_count')
->leftJoin('likings', function ($join) {
$join->on('likings.post_id', '=', 'posts.id')
->where('likings.isActive', '=', 1);
})
->groupBy('posts.id')
->orderBy('likes_count', 'desc')
->take(5)
->get();
And this is the error:
SQLSTATE[42000]: Syntax error or access violation: 1055 'database.posts.user_id' isn't in GROUP BY
(SQL: select posts.*, count(likings.id) as likes_count from 'posts' left join 'likings' on 'likings'.'post_id' = 'posts'.'id' and 'likings'.'isActive' = 1 group by 'posts'.'id' order by 'likes_count' desc limit 5)
or just exequte this query
Post::with(['likes' => function ($query){
$query->where('active', 1);
}]);
and sort it by php if its too hard in mysql. For ex some PostTransformer class
Post::selectRaw('posts.*, count(likes.id) as likes_count')
->leftJoin('likes', function ($join) {
$join->on('likes.post_id', '=', 'posts.id')
->where('likes.is_active', '=', 1);
})
->groupBy('posts.id')
->orderBy('likes_count', 'desc')
->take(5)
->get();
or subselect:
Post::select('*')->selectSub(function ($q) {
$q->from('likes')
->whereRaw('likes.post_id = posts.id')
->where('is_active', 1)
->selectRaw('count(*)');
}, 'likes_count')
->orderBy('likes_count', 'desc')
->take(5)
->get();
Post::join(DB::raw('(select post_id, count(post_id) as number from likes) as likes_count ON posts.id = likes_count.post_id where likes_count.active = 1'), null)->orderBy('likes_count.number', 'desc')->limit(5);
I wrote that without checking this out, so don't hate

Multiple wheres in Laravel join

I have:
$buyingNet = DB::table('parts_enquiries_buying AS PEB')
->select(DB::raw('SUM((PEB.quantity*PEB.net)/IF(ISNULL(currencyRate), rate, currencyRate)) AS total'))
->join('currencies_rates AS CR', function ($q) {
$q->on('CR.id', '=', 'PEB.currencyId')
//->where(DB::raw('YEAR(CR.date)'), '=', date('Y'))
->where(DB::raw('MONTH(CR.date)'), '=', date('m'));
})
->leftJoin('jobs', 'jobs.enquiryId', '=', 'PEB.enquiryId')
->leftJoin('invoices_out AS IO', 'IO.jobId', '=', 'jobs.id')
->where('PEB.enquiryId', $enquiryId)
->first()->total;
If I uncomment the where that matches the year I get null returned, but all the rows that should be there are there.
Is my syntax correct? It should translate as:
... YEAR(CR.date) = ? AND MONTH(CR.date) =? ...
I believe the issue here is that Query builder doesn't understand your DB::raw statement within the ->where clause.
You should do as folllows:
->whereRaw("YEAR(CR.date) = '". date('Y')."'")
->whereRaw("MONTH(CR.date) = '". date('n')."'")
for the month clause you need to use n instead of m since MySQL MONTH returns a single digit for months below 10.