Laravel query count total rows - php

I have this query:
$counts = DB::table('projects')
->join('prject_links', 'prject_links.project_id', '=', 'projects.id')
->join('links', 'links.id', '=', 'prject_links.link_id')
->join('segments', 'segments.id', '=', 'links.segment_id')
->join('hthree_regions', 'hthree_regions.id', '=', 'segments.hthree_id')
->join('areas', 'areas.id', '=', 'hthree_regions.area_id')
->join('zone_regions', 'zone_regions.id', '=', 'areas.zone_id')
->select(
'zone_regions.id as regions',
'areas.id as provinces',
'hthree_regions.id as cities',
'segments.id as segments'
)
->get();
what I'm looking to have as result is something like:
counts => [
regions => 20,
provinces => 10,
cities => 7,
segments => 5
];
What do i get currently is confusing result like:
any idea about how to fix my query?

Use groupBy and count(distinct field) to get the field's count in each project:
->selectRaw(
"CONCAT('project ', projects.id) as project,
COUNT(DISTINCT zone_regions.id) as regions,
COUNT(DISTINCT areas.id) as provinces,
COUNT(DISTINCT hthree_regions.id) as cities,
COUNT(DISTINCT segments.id) as segments"
)
->groupBy('projects.id')
->get();

This might be your solution. Run it and let me know if that helps
$counts = DB::table('projects')
->join('prject_links', 'prject_links.project_id', '=', 'projects.id')
->join('links', 'links.id', '=', 'prject_links.link_id')
->join('segments', 'segments.id', '=', 'links.segment_id')
->join('hthree_regions', 'hthree_regions.id', '=', 'segments.hthree_id')
->join('areas', 'areas.id', '=', 'hthree_regions.area_id')
->join('zone_regions', 'zone_regions.id', '=', 'areas.zone_id')
->groupBy('projects.id')
->selectRaw(
'count(zone_regions.id) as regions',
'count(areas.id) as provinces',
'count(hthree_regions.id) as cities',
'count(segments.id) as segments'
)
->get();

Related

Laravel WHERE scope on JOIN

I am trying to get "shifts" and get all records I have,
But I join it with orders and run where on orders by delivery_date here "the shift" which has no orders erased
now I need to make the where only on orders and not affect on shifts
Shift::leftJoin('mt_plans', 'mt_plans.shift_id', '=', 'shifts.id')
->leftJoin('subscriptions', 'subscriptions.plan_id', '=', 'mt_plans.plan_id')
->join('orders', 'orders.subscription_id', '=', 'subscriptions.id')
->join('mt_order_details', 'mt_order_details.order_id', '=', 'orders.id')
->join('mt_item', 'mt_item.item_id', '=', 'mt_order_details.item_id')
->where('orders.delivery_date', $request->date)
->whereIn('orders.status', [OrderStatus::ACCEPTED, OrderStatus::ASSIGNED, OrderStatus::FAILED, OrderStatus::SUCCESSFUL])
->select([
'mt_item.item_id as meal_id',
'mt_item.en_name',
'mt_item.color',
'mt_item.label_number',
'shifts.id as shift_id',
'shifts.title',
'shifts.start_time',
'shifts.end_time',
'shifts.pickup_time'
])
->get();
You need a left join where your condition applies:
Shift::leftJoin('mt_plans', 'mt_plans.shift_id', '=', 'shifts.id')
->leftJoin('subscriptions', 'subscriptions.plan_id', '=', 'mt_plans.plan_id')
->leftJoin('orders', function($q) use($request) {
$q->on('orders.subscription_id', '=', 'subscriptions.id');
$q->where('orders.delivery_date', '=', $request->date);
})
->leftJoin('mt_order_details', 'mt_order_details.order_id', '=', 'orders.id')
->leftJoin('mt_item', 'mt_item.item_id', '=', 'mt_order_details.item_id')
->whereIn('orders.status', [OrderStatus::ACCEPTED, OrderStatus::ASSIGNED, OrderStatus::FAILED, OrderStatus::SUCCESSFUL])
->select([
'mt_item.item_id as meal_id',
'mt_item.en_name',
'mt_item.color',
'mt_item.label_number',
'shifts.id as shift_id',
'shifts.title',
'shifts.start_time',
'shifts.end_time',
'shifts.pickup_time'
])
->get();
Then you keep all "shifts" but join only order with delivery_date condition.
Keep in mind that it will retrieve all "shifts" where where condition applies. The orders will be null if doesn't match the id and delivery_date

Laravel select all rows if id exists in another table and a column has specific values on that table

I have 4 tables:
notices (id, title, desc, is_published)
notices_to_districts (id, notice_id, district_id)
notices_to_employees (id, notice_id, user_id)
notices_to_establishments (id, notice_id, establishment_id)
I want to get all unique notices if,
notices_to_districts has a specific district_id, or
notices_to_employees has a specific user_id, or
notices_to_establishments has a specific establishment_id
I am trying -
$notices = Notice::join('notices_to_districts', 'notices_to_districts.notice_id', '=', 'notices.id')
->join('notices_to_establishments', 'notices_to_establishments.notice_id', '=', 'notices.id')
->join('notices_to_employees', 'notices_to_employees.notice_id', '=', 'notices.id')
->where('district_id', '=', $user_district_id)
->orWhere('establishment_id', '=', $user_establishment_id)
->orWhere('user_id', '=', $user_id)
->where('is_published', '=', 1)->get();
You should use Closure Parameter Grouping or else, your "orWhere" will not work as you wish.
$notices = Notice::join('notices_to_districts', 'notices_to_districts.notice_id', '=', 'notices.id')
->join('notices_to_establishments', 'notices_to_establishments.notice_id', '=', 'notices.id')
->join('notices_to_employees', 'notices_to_employees.notice_id', '=', 'notices.id')
->where('district_id', '=', $user_district_id)
->where('is_published', '=', 1)
->where(
function ($query) use ($user_establishment_id, $user_id) {
$query->orWhere('establishment_id', '=', $user_establishment_id)
->orWhere('user_id', '=', $user_id);
}
)
->get();
Like this example, the SQL will have the correct parentesis around your clause.
I solved it -
$notice_ids_of_district = Notices_to_district::select('notice_id')->where('district_id', '=', $user_district_id)->get();
$notice_ids_of_establishment = Notices_to_establishment::select('notice_id')->where('establishment_id', '=', $user_establishment_id)->get();
$notice_ids_of_employee = Notices_to_employee::select('notice_id')->where('user_id', '=', $user_id)->get();
$notices = Notice::whereIn('id', $notice_ids_of_district)
->orWhereIn('id', $notice_ids_of_establishment)
->orWhereIn('id', $notice_ids_of_employee)
->get();

How can I show and pagination two queries in the laravel blade?

I want to show $personnals and $users in a table in the blade.
I know, I have to use #foreach. But I can't. Because, I have two queries and I can't pagination and show those.
$personnals = DB::table('orders')
->where('pay_type', 1)
->leftJoin('personnels', 'orders.personnel_id', '=', 'personnels.id')
->leftJoin('users', 'personnels.user_id', '=', 'users.id')
->select(['name AS personnelName', 'lastname AS personnelLastName'])
->get();
$users = DB::table('orders')
->where('pay_type', 1)
->leftJoin('users', 'orders.user_id', '=', 'users.id')
->select(['name AS userName', 'lastname AS userLastName', 'orderCode'])
->get();
$personnals has 100 elements and $users has 100 elements ,too. Every elements is an array. I want to merge these arrays together and have one array with 100 array elements.
For example: I want something like $result:
$personnals = [ [ 'a'=>'blue', 'b'=>'red' ], [ 'a'=>'green', 'b'=>'black' ] ];
$users = [ [ 'c'=>'yellow', 'd'=>'orange' ], [ 'c'=>'white', 'd'=>'pink' ] ];
$result = [
[ 'a'=>'blue', 'b'=>'red', 'c'=>'yellow', 'd'=>'orange' ] ,
[ 'a'=>'green', 'b'=>'black', 'c'=>'white', 'd'=>'pink' ]
];
How can I show these in blade with pagination?
OR
Can I show all in one query?How?
Thanks.
you can use union
$personnals = DB::table('orders')
->where('pay_type', 1)
->leftJoin('personnels', 'orders.personnel_id', '=', 'personnels.id')
->leftJoin('users', 'personnels.user_id', '=', 'users.id')
->select(['name', 'lastname', 'orderCode']);
$result = DB::table('orders')
->where('pay_type', 1)
->leftJoin('users', 'orders.user_id', '=', 'users.id')
->select(['name', 'lastname', 'orderCode'])
->union($personnals)
->get();
try above!
As you want only 100 result instead of 200 than so you are expecting join instead of union
$result = DB::table('orders')
->where('pay_type', 1)
->leftJoin('personnels', 'orders.personnel_id', '=', 'personnels.id')
->leftJoin('users AS u1', 'personnels.user_id', '=', 'u1.id')
->leftJoin('users AS u2', 'orders.user_id', '=', 'u2.id')
->select(['u2.name AS userName', 'u2.lastname AS userLastName', 'orderCode', 'u1.name AS personnelName', 'u1.lastname AS personnelLastName'])
->get();

syntax to join a table twice in laravel

I'm trying to join the below 3 tables. The issue is in the part where I want to join posts.id to the shares.post_id using 'AND' operator which is not correct. What is the correct syntax to do that ?
$sharedPosts = DB::table('shares')
->join('users', 'users.id', '=', 'shares.user_id')
->join('posts', 'posts.user_id', '=', 'users.id' , 'AND' , 'posts.id', '=', 'shares.post_id')
->where('shares.user_id', '=', $myFriends)
->get();
Try aliasing:
$sharedPosts = DB::table('shares')
->join('users', 'users.id', '=', 'shares.user_id')
->join('posts as p1', 'p1.user_id', '=', 'users.id' , 'AND' , 'p1.id', '=', 'shares.post_id')
->join('posts as p2', 'p2.id', '=', 'shares.post_id')
->where('shares.user_id', '=', $myFriends)
->get();
You cannot join a table twice with no alias.
Although if you have 2 clauses in your join, I think you ought to do as in the documentation :
$sharedPosts = DB::table('shares')
->join('users', 'users.id', '=', 'shares.user_id')
->join('posts as p1', , function($join){
$join->on('p1.user_id', '=', 'users.id')
->on('p1.id', '=', 'shares.post_id')
})
->join('posts as p2', 'p2.id', '=', 'shares.post_id')
->where('shares.user_id', '=', $myFriends)
->get();
Edit (with one posts join):
$sharedPosts = DB::table('shares')
->join('users', 'users.id', '=', 'shares.user_id')
->join('posts', , function($join){
$join->on('posts.user_id', '=', 'users.id')
->on('posts.id', '=', 'shares.post_id')
})
->where('shares.user_id', '=', $myFriends)
->get();

Perform JOIN on three or four different tables in Laravel syntax

TABLES X(ID,A_ID)A(ID,B_ID),B(ID,C_ID),C(ID,D_ID)D(id,VALUE)
I want to retrieve the value of D table using laravel syntax on basis of X table Id and perform a JOIN with other tables.
Please post answers only in laravel syntax. In other format I can do. I am new to it so.
X::select('value')
->join('a', 'X.a_id', '=', 'a.id')
->join('b', 'a.b_id', '=', 'b.id')
->join('c', 'b.c_id', '=', 'c.id')
->join('d', 'c.d_id', '=', 'd.id')
->where('x.id', '=', $val)
->get();
But it is not working. please provide me proper solution. Right now I am using PHP logic to get the value, rather than optimise the query.
There are many ways, but this is the basic:
$rows = DB::table('shares')
->join('users', 'users.id', '=', 'shares.user_id')
->join('follows', 'follows.user_id', '=', 'users.id')
->where('follows.follower_id', '=', 3)
->get();
doc
Try this:
DB::table('X')
->join('a', 'X.a_id', '=', 'a.id')
->join('b', 'a.b_id', '=', 'b.id')
->join('c', 'b.c_id', '=', 'c.id')
->join('d', 'c.d_id', '=', 'd.id')
->select('D.value')
->where('x.id', '=', $val)
->get();
$result = X::select('a.value', 'd.*')
->join('a', 'x.a_id', '=', 'a.id')
->join('b', 'a.b_id', '=', 'b.id')
->join('c', 'b.c_id', '=', 'c.id')
->join('d', 'c.d_id', '=', 'd.id')
->where('x.id', '=', $val)
->get();
foreach ($result as $row) {
# code...
}

Categories