Convert SQL into Laravel Eloquent - laravel

I have this SQL query:
SELECT
m1.id
FROM
messages m1
WHERE
m1.to_id = 1 AND m1.created_at < (
SELECT
m2.created_at
FROM
messages m2
WHERE
m2.from_id = m1.to_id AND m2.to_id = m1.from_id)
GROUP BY
m1.id
How can i convert into eloquent? I done this until now, but a don't know what to do in the part of where on subquery.
Message::where('to_id', 1)
->where('created_at', '<', function($q) {
$q->from('messages');
$q->select('created_at');
})
->select('id')
->groupBy('id')
->get();

You can try this:
Message::where('to_id', 1)
->where('created_at', '<', function($q) {
$q->from('messages AS m2')
->select('created_at')
->where('m2.from_id ','=', 'messages.to_id ')
->where('m2.to_id','=','messages.from_id');
})
->select('id')
->groupBy('id')
->get();

Related

select from table (laravel) - where and orWhere

So, I'm using laravel and I want to make this query to work in laravel 'formula'
SELECT * FROM `complaints` WHERE (`fID` = 0) AND (`hide_topic` = 0 OR (`hide_topic` <= 0 OR (`hide_topic` > 3 AND byID = 52))) ORDER BY `status` ASC, `id` DESC
And I made something like this in laravel but not sure that selects correctly like the query above does.
DB::table('complaints')
->where('fID', '=', 0)
->where('hide_topic', '=', 0)
->orWhere('hide_topic', '<', 0)
->orWhere('hide_topic', '>', 3)
->where('byID', '=', 52)
->orderBy('status', 'asc')
->orderBy('id', 'desc')
->get();
Any help?
If you carefully examine your query. You can definitely remove some extra filters. If you see inner where if hide_topic <= 0 it also covers hide_topic =0 so you can reduce your query to.
SELECT *
FROM `complaints`
WHERE `fID` = 0
AND (`hide_topic` <= 0 OR (`hide_topic` > 3 AND byID = 52))
ORDER BY `status` ASC, `id` DESC
Best thing from laravel is that you can actually see the query that will be executed using query builders or eloquent model using toSql method. You can use toSql method at place of get, all or first functions.
$result = DB::table('complaints')
->where('fID', '=', 0)
->where(function($query) {
$query->where('hide_topic', '<=', 0)
->orWhere(function($query) {
$query->where('hide_topic', '>', 3)
->where('byID', '=', 52);
});
})
->orderBy('status', 'asc')
->orderBy('id', 'desc')
->get();
// to check the query just replace `->get();` to `->toSql();` in above query.
Now if you don't want any modifications in your existing query. You can reference to #OMR answer. Still I'll put it here.
$result = DB::table('complaints')
->where('fID', '=', 0)
->where(function($query) {
$query->where('hide_topic', '=', 0)
->orWhere(function($query) {
$query->where('hide_topic', '<=', 0)
->orWhere(function($query) {
$query->where('hide_topic', '>', 3)
->where('byID', '=', 52);
});
});
})
->orderBy('status', 'asc')
->orderBy('id', 'desc')
->get(); -- use toSql() to actually see the query before bindings.
you simply use where with clouser for every compound condition:
$admin_level=3;
$playerid=52;
DB::table('complaints')->where('fID', '=', 0)
->where(function ($query)use($admin_level,$playerid){
$query->where('hide_topic', '=', 0)->orWhere(function ($query)use($admin_level,$playerid){
$query->Where('hide_topic', '<', 0)->orWhere(function ($query)use($admin_level,$playerid){
$query ->Where('hide_topic', '>', $admin_level)
->where('byID', '=', $playerid);
});
});
})
->orderBy('status', 'asc')
->orderBy('id', 'desc')
->get();

Laravel query not giving desired result

Can someone help fix this query. Query is returning null result for "j.code" and "accounts.title". And I am 100% sure that it should return result. I think my left join are missing something. Is this the proper way of using left join within a left join.
$query = DB::table('autostk')
->where('autostk.branchid', $branch_id)
->where('autostk.itemcode',$request->itemcode)
->whereDate('autostk.date','<=',$request->tdate)
->leftjoin('journal AS j', function($join) use ($branch_id) {
$join->on('autostk.refno', '=', 'j.vno')
->where('j.code', '>=', 100)
->where('j.branchid', $branch_id)
->where('j.vtype', '=', 'autostk.vtype')
->leftjoin('accounts', 'j.code', '=', 'accounts.code')
->where('accounts.branchid', $branch_id);
})
->select('j.code','accounts.title','autostk.*')
->orderBY('date')->get()
->map(function ($item, $key) {
return (array) $item;
})
->all();
The raw query being generated is :
select `j`.`code`, `accounts`.`title`, `autostk`.* from `autostk`
left join (`journal` as `j` left join `accounts` on `j`.`code`=`accounts`.`code`)
on `autostk`.`refno` = `j`.`vno` and `j`.`code` >= ? and `j`.`branchid` = ?
and `j`.`vtype` = ? and `accounts`.`branchid` = ? where `autostk`.`branchid` = ?
and `autostk`.`itemcode` = ? and date(`autostk`.`date`) <= ? order by
`autostk`.`date` asc
UPDATE :
While checking the QueryLog i noticed that the binding for 'j'.'vtype' is "autostk.vtype"
Applying the query in workbench with 'autostk.vtype' returned null results.
But when I changed it to 'autostk'.'vtype' the results showed up correctly.
How to make this change in Laravel Eloquent ?
Please try like below:
$query = DB::table('autostk')
->where('autostk.branchid', $branch_id)
->where('autostk.itemcode',$request->itemcode)
->whereDate('autostk.date','<=',$request->tdate)
->leftjoin('journal as j', function($join) use ($branch_id) {
$join->on('autostk.refno', '=', 'j.vno')
->where('j.code', '>=', 100)
->where('j.branchid', $branch_id)
->where('j.vtype', '=', 'autostk.vtype')
->leftjoin('accounts', 'j.code', '=', 'accounts.code')
->where('accounts.branchid', $branch_id);
})
->select('j.code','accounts.title','autostk.*')
->orderBy('autostk.date')->get()
->map(function ($item, $key) {
return (array) $item;
})
->all();
There is one problem:
->orderBy('autostk.date')
And you can use toArray() instead of map() like this
->orderBy('autostk.date')->get()->toArray();
Found the solution. Correct query is :
$query = DB::table('autostk')
->where('autostk.branchid', $branch_id)
->where('autostk.itemcode',$request->itemcode)
->whereDate('autostk.date','<=',$request->tdate)
->leftjoin('journal AS j', function($join) use ($branch_id) {
$join->on('autostk.refno', '=', 'j.vno')
->on('autostk.vtype', '=', 'j.vtype')
->where('j.code', '>=', 100)
->where('j.branchid', $branch_id)
->leftjoin('accounts', 'j.code', '=', 'accounts.code')
->where('accounts.branchid', $branch_id);
})
->select('j.code','accounts.title','autostk.*')
->orderBY('autostk.date')->get()
->map(function ($item, $key) {
return (array) $item;
})
->all();
->leftjoin('journal as j', function($join) use ($branch_id) {
as instead of AS

Select unique records from child with condition on parent relationship

I have two tables, Shows and Episodes, each episode has show_id linking them one to many.
Now I need to get latest 6 episodes, one per show, where show.active is true
I've tried the following code:
$episodes = Episode::select(DB::raw('t.*'))
->from(DB::raw('(SELECT * FROM episodes ORDER BY id DESC) t'))
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->groupBy('t.show_id')
->take(6)
->get();
Unfortunately, I get the following:
Column not found: 1054 Unknown column 'episodes.show_id' in 'where clause' (SQL: select t.* from (SELECT * FROM episodes ORDER BY id DESC) t where exists (select * from shows where episodes.show_id = shows.id and active = 1) group by t.show_id limit 6)
I've also tried:
$episodes = Episode::where('active', true)
->orderBy('id', 'DESC')
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->groupBy('show_id')
->take(6)
->get();
It shows no error, but doesn't return latest of each show, groupBy gets the first record, I need the latest
This should work:
$episodes = Episode::where('active', true)
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->groupBy('show_id')
->orderBy('id', 'DESC')
->take(6)
->get();
You can try this
$episodes = Episode::selectRaw('max(id) as id, show_id')
->whereHas('show', function($query) {
$query->where('active', '=', true);
})
->orderBy('id', 'DESC')
->groupBy('show_id')
->take(6)
->get();
You can use a WHERE IN subquery:
$ids = Episode::selectRaw('max(id)')
->whereHas('show', function ($query) {
$query->where('active', '=', true);
})->groupBy('show_id');
$episodes = Episode::whereIn('id', $ids)
->take(6)
->get();

Why query returns empty collection?

I have the following query was built by Laravel:
$res = Announcement::whereExists(function ($query) {
$query->select(DB::raw(1))
->from('announcement_category')->join('user_category', 'user_category.category_id', '=', 'announcement_category.category_id')
->where('user_category.user_id', '=', 1)
->where('announcement_category.announcement_id', '=', 'announcements.id');
});
dd($res->get());
The code above gives me empty collection: dd($res->get());.
The plain SQL code of this query is:
select * from `announcements` where exists (select 1 from
`announcement_category` inner join `user_category` on
`user_category`.`category_id` = `announcement_category`.`category_id` where `user_category`.`user_id` = 1
and `announcement_category`.`announcement_id` = announcements.id)
and `announcements`.`deleted_at` is null
If execute this directly in MySQL, I get two result rows.
But why dd($res->get()); retuns me empty?
I don't think there is a whereExists in eloquent model... try this:
$res = DB::table('announcement')->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('announcement_category')->join('user_category', 'user_category.category_id', '=', 'announcement_category.category_id')
->where('user_category.user_id', '=', 1)
->where('announcement_category.announcement_id', '=', 'announcements.id');
})->get();

Laravel 4 advanced wheres

I have my query working perfectly in mySQL, however am struggling to use the advanced wheres inside the laravel query builder.
Can anyone assist in converting this at all?
So far I have:
LARAVEL
$start_request = '2014-12-18 09:00';
$end_request = '2014-12-18 10:00';
$events= DB::table('events')
->where('hotel_id', 4)
->orWhere(function($query)
{
$query->where($start_request, '<=', 'start_time')
->where($end_request, '>', 'start_time');
})
->orWhere(function($query)
{
$query->where($start_request, '>=', 'start_time')
->where($end_request, '<', 'end_time');
})
->get();
mySQL
SELECT id, title, description, start_time, end_time FROM events where hotel_id = 4 and (('2014-12-18 09:00' <= start_time and '2014-12-18 10:00' > start_time)
or ('2014-12-18 09:00' >= start_time and '2014-12-18 10:00' < end_time));
Can you try this?
$start_request = '2014-12-18 09:00';
$end_request = '2014-12-18 10:00';
$events= DB::table('events')
->where('hotel_id', 4)
->where(function($query) use($start_request, $end_request) {
$query->where(function($subquery) use($start_request, $end_request){
$subquery->where('start_time', '>=', $start_request)
->where('start_time', '<', $end_request);
});
$query->orWhere(function($subquery1) use($start_request, $end_request) {
$subquery1->where('start_time', '<=', $start_request)
->where('end_time', '>', $end_request);
});
})
->get();
Something like this should do the job:
$start_request = '2014-12-18 09:00';
$end_request = '2014-12-18 10:00';
$events = DB::table('events')
->where('hotel_id', 4)
->where(function ($q) use ($start_request, $end_request) {
$q->where(function ($query) use ($start_request, $end_request) {
$query->where($start_request, '<=', 'start_time')
->where($end_request, '>', 'start_time');
})
->orWhere(function ($query) use ($start_request, $end_request) {
$query->where($start_request, '>=', 'start_time')
->where($end_request, '<', 'end_time');
});
})
->select('id', 'title', 'description', 'start_time', 'end_time')
->get();

Resources