Laravel nested join queries with query builder - php

This is a search function that returns each member with their most recent year registered.
I got it working with a DB::raw() call. But can't get it working with the query builder.
Working Code:
$query = DB::table('membership as m');
$query->join(
DB::raw(
'(SELECT my.*
FROM membership_years my
INNER JOIN (
SELECT member_id,MAX(membership_year) AS max_my
FROM membership_years
GROUP BY member_id
) my2
ON my.member_id = my2.member_id
AND my.membership_year = my2.max_my
) my'
)
,'m.id','=','my.member_id');
My attempt on query builder code:
$query = DB::table('membership as m');
$query->join('membership_years as my',
function($j1){
$j1->join('membership_years as my2',
function($j2){
$j2->where('my.membership_year','=','MAX(my2.membership_year)')
->on('my.member_id','=','my2.member_id');
}
)->on('m.id','=','my.member_id');
}
);
The resulting error is:
Call to undefined method Illuminate\Database\Query\JoinClause::join()
I'm not sure if this is because the $j2 doesn't have access to the join method anymore?
Raw MySQL query:
SELECT my.membership_year,m.*
FROM membership AS m
INNER JOIN
(
SELECT my1.*
FROM membership_years my1
INNER JOIN
(
SELECT member_id,MAX(membership_year) AS max_my
FROM membership_years
GROUP BY member_id
) my2
ON my1.member_id = my2.member_id
AND my1.membership_year = my2.max_my
) my
ON m.id = my.member_id
ORDER BY m.id ASC

Way 1. You can write part of the query with builder:
$query = DB::table('membership as m')
->select('my.membership_year', 'm.*')
->join(DB::raw('(
SELECT my1.*
FROM membership_years my1
INNER JOIN (
SELECT member_id, MAX(membership_year) AS max_my
FROM membership_years
GROUP BY member_id
) my2
ON my1.member_id = my2.member_id
AND my1.membership_year = my2.max_my
) my'),
'm.id', '=', 'my.member_id')
->orderBy('m.id');
Way 2. Also you can write subqueries and use toSql() method:
$sub1 = DB::table('membership_years')
->select('member_id', DB::raw('MAX(membership_year) AS max_my'))
->groupBy('member_id');
$sub2 = DB::table('membership_years as my1')
->select('my1.*')
->join(DB::raw('(' . $sub1->toSql() . ') my2'),
function ($join) {
$join
->on('my1.member_id', '=', 'my2.member_id')
->on('my1.membership_year', '=', 'my2.max_my');
});
$query = DB::table('membership as m')
->select('my.membership_year', 'm.*')
->join(DB::raw('(' . $sub2->toSql() . ') my'), 'm.id', '=', 'my.member_id')
->orderBy('m.id');

Related

How to transform traditional query into Laravel E.L.O.Q.U.E.N.T QUERY?

Can someone help me to convert this query into Laravel ELOQUENT? The query is below on the screenshot link and also on comment section
DB::select('SELECT t1.*
FROM messages AS t1
INNER JOIN
(
SELECT
LEAST(sender_id, receiver_id) AS sender_id,
GREATEST(sender_id, receiver_id) AS receiver_id,
MAX(id) AS max_id
FROM messages
GROUP BY
LEAST(sender_id, receiver_id),
GREATEST(sender_id, receiver_id)
) AS t2
ON LEAST(t1.sender_id, t1.receiver_id) = t2.sender_id AND
GREATEST(t1.sender_id, t1.receiver_id) = t2.receiver_id AND
t1.id = t2.max_id
WHERE t1.sender_id = ? OR t1.receiver_id = ?
', [$id, $id]);
Considering you have two variables to store sender and receiver id for filtering.
$sender_id = 10;
$receiver_id = 12;
$sub = DB::table('messages')
->selectRaw(
"LEAST(sender_id, receiver_id) AS sender_id,
GREATEST(sender_id, receiver_id) AS receiver_id,
MAX(id) AS max_id"
)
->groupByRaw('LEAST(sender_id, receiver_id), GREATEST(sender_id, receiver_id)');
$main = DB::table('messages as t1')
->joinSub($sub, 't2', function ($join) {
$join->on(function($query){
return $query->whereRaw('LEAST(t1.sender_id, t1.receiver_id) = t2.sender_id')
->whereRaw('GREATEST(t1.sender_id, t1.receiver_id) = t2.receiver_id')
->whereRaw('t1.id = t2.max_id');
});
})
->selectRaw('t1.*')
->where('t1.sender_id', '=', $sender_id)
->where('t1.receiver_id', '=', $receiver_id)
->get();
You can replace get with toSql method to see what query will be generated.
Also I used multiple whereRaw in on clause to increase the readability, you can merge them in single whereRaw too.
See also Joining distinct table in laravel for more info.

laravel query for bewteen

I want to convert the sql query to laravel query which is working fine in sql
select
a.id,
a.assigned_user_name,
a.lead_stage_c,
a.meeting_start_date,
a.call_start_date
from
mgl_report_targets as a
left join
dcalendardate b
on b.datevalue = a.meeting_start_date
left join
dcalendardate c
on c.datevalue = a.call_start_date
where
(
a.lead_stage_c = 'Target-MQL'
)
and
(
b.datevalue between '2020-07-31' and '2020-09-01'
)
or
(
c.datevalue between '2020-07-31' and '2020-09-01'
)
and a.active_status = '1'
and a.lead_stage_c = 'Target-MQL'
In laravel I have tried as
$report_details=DB::table('mgl_report_targets')->where('active_status',1);
$report_details=$report_details->leftjoin('dcalendardate as a','a.datevalue','=',DB::raw("mgl_report_targets.meeting_start_date::date"))->leftjoin('dcalendardate as b','b.datevalue','=',DB::raw("mgl_report_targets.call_start_date::date"));
$report_details=$report_details->where(function ($query) {
return $query->whereBetween('a.datevalue',['2020-07-31','2020-09-01']);
})
->orWhere(function ($query) {
return $query->whereBetween('b.datevalue',['2020-07-31','2020-09-01']);
});
$report_details=$report_details->where('mgl_report_targets.lead_stage_c','=','Target-MQL')->select('mgl_report_targets.id','mgl_report_targets.assigned_user_name','mgl_report_targets.meeting_start_date','mgl_report_targets.call_start_date','mgl_report_targets.lead_stage_c')->get();
but between query not query as expected.
What I did wrong.

how to write sql query to laravel

i have a sql query like this and i want to convert it to laravel how i can do it?
i have try it, but i confusing on wherein and join
sql query
SELECT MIN(StartFrom) as StartFrom,MAX(EndTo) as EndTo from appointmentsettings
WHERE day=1
and PersonID IN (
SELECT p.id
FROM users p
JOIN appointmentsettings aps ON p.id = aps.PersonID
WHERE p.active=1 AND aps.CompanyID = 1 OR aps.PersonID IN(
SELECT cps.user_id
from companypersonstructs cps
WHERE cps.CompanyID =1
) group by aps.PersonID
)
and active=1
here what i try
Appointmentsetting::select('StartFrom', 'EndTo')
->min('StartFrom')
->max('EndTo')
->where(['Day'=>$day, 'Active'=>1])
->whereIn('PersonID', function ($query) use ($id) {
$query->select('p.id')
->from('users as p')
$query->join('appointmentsettings as aps', 'p.id', '=', '')
->where(["user_id" => $id, 'Active' => 1])->get();
})->orderBy('id')->get();
Appointmentsetting::select('StartFrom', 'EndTo')
->min('StartFrom')
->max('EndTo')
->where(['Day'=>$day, 'Active'=>1])
->whereIn('PersonID', function ($query) use ($id) {
$query->select('p.id')
->from('users as p')
->join('appointmentsettings as aps', 'p.id', '=', '')
->where(["user_id" => $id, 'Active' => 1]);
})->orderBy('id')->get();
You have an error in your join inside the function. Try the above code.
Also you must use get() only at the end of the query and not inside the function itself.
DB Query way
DB::table('appointmentsettings')->join('users','p.id','=','')
->select(DB::raw('MIN(StartFrom) as StartFrom','Max(EndTo) as EndTo'))
->where([['user_id',$id],['Active','1']])
->groupBy('appointmentsettings.PersonID)
->orderBy('id','ASC')
->get();

How to effectively using laravel 5.5 eloquent on complex join and group

I have this query that successfully run on mysql workbench:
SELECT
any_value(u.username),
any_value(b.name),
any_value(gc.visit_cycle_id),
any_value(gc.group_number),
any_value(dc.total_customer),
count(*) as total_day
FROM
trackgobackenddb.group_cycles gc
LEFT JOIN (
SELECT
any_value(dc.group_cycle_id) as group_cycle_id,
count(*) as total_customer
FROM
trackgobackenddb.destination_cycles dc
GROUP BY dc.group_cycle_id
) dc ON dc.group_cycle_id = gc.id
LEFT JOIN visit_cycles vc ON gc.visit_cycle_id = vc.id
LEFT JOIN users u ON vc.user_id = u.id
LEFT JOIN branches b ON vc.branch_id = b.id
GROUP BY gc.visit_cycle_id, gc.group_number;
How to convert that query so I can use laravel eloquent or query builder?
You can use DB::select to run complex raw SQL
$sql = "";
$data = DB::select($sql);
Here's my untested attempt using the query builder:
DB::table('group_cycles AS gc')
->leftJoin('destination_cycles AS dc', function ($join) {
$join->on('dc.group_cycle_id', '=', 'gc.id')
->select(['dc.group_cycle_id AS group_cycle_id', DB::raw('select count(*) AS total_customer')]);
})
->leftJoin('visit_cycles AS vc', function ($join) {
$join->on('gc.visit_cycle_id', '=', 'vc.id');
})
->leftJoin('users AS u', function ($join) {
$join->on('vc.user_id', '=', 'u.id');
})
->leftJoin('branches AS b', function ($join) {
$join->on('vc.branch_id', '=', 'b.id');
})
->groupBy('gc.visit_cycle_id', 'gc.group_number')
->get();

Using And Clause in Laravel Query Bulider

I have the following query:
SELECT
customers.CustCompanyName,
addresses.AddressLine1,
orders.*
FROM orders
INNER JOIN customers
ON orders.CustID = customers.CustID
INNER JOIN customer_addresses
ON customer_addresses.CustID = customers.CustID
INNER JOIN addresses
ON customer_addresses.AddressID = addresses.AddressID
AND orders.CustAddID = customer_addresses.CustAd
How do I incorporate the AND clause in using laravel Query Builder:
$orders = DB::table('orders')
->join('customers', 'orders.CustID', '=', 'customers.CustID')
->join('customer_addresses','customer_addresses.CustID', '=' , 'customers.CustID' )
->join('addresses','customer_addresses.AddressID','=','addresses.AddressID')->AND
I can't find any working examples using the AND clause.
For:
INNER JOIN addresses
ON customer_addresses.AddressID = addresses.AddressID
AND orders.CustAddID = customer_addresses.CustAd
you should use:
->join('addresses', function($join) {
$join->on('customer_addresses.AddressID', '=', 'addresses.AddressID')
->whereRaw('orders.CustAddID = customer_addresses.CustAd');
});
You can also look at Joins in Query Builder for details

Categories