Is there a way to Select all where a join fails:
something like:
// Pseudo
$unit = User::from( 'users' )
->select( 'users.*' )
->whereJoinFails( 'suppliers', 'users.id', '=', 'suppliers.user_id' );
I have tried:
// Returns all users
$unit = User::from( 'users' )
->select( 'users.*' )
->leftJoin( 'suppliers', 'users.id', '=', 'suppliers.user_id' );
and
// Returns all users but the one that doesn't satisfy is duplicated
$unit = User::from( 'users' )
->select( 'users.*' )
->join( 'suppliers', 'users.id', '!=', 'suppliers.user_id' );
Left Join will always display the data on the left side of the join even if it is null. This way you can see all the records that are missing in the suppliers table because it will show up as a null. This should work:
User::from( 'users' )
->select( 'users.*' )
->leftJoin('suppliers', 'users.id', '=', 'suppliers.user_id')
->whereNull('suppliers.user_id')
->get();
Alternative solution for this would be:
$cat = User::whereNotIn('id',
DB::table('suppliers')->distinct()->lists('user_id')
)->get();
but in this case 2 queries to database would be executed, for example:
select distinct `user_id` from `suppliers`;
select * from `users` where `id` not in ('1', '2', '5', '6', '7', '8', '9', '10');
Related
Hi I would like to ask is there any way to refer the 2 foreign key to 1 primary table id?
This is my code.
$job_postings = JobPosting::select(
'job_postings.id as job_posting_id',
'job_postings.qualifications',
'job_postings.created_at',
'job_postings.updated_at',
'job_postings.created_by',
'job_postings.approved_by',
'dealerships.dealership_name',
'departments.department_name',
'positions.position_name',
'users.name as created_by_name', (**This is the issue please help**)
'users.name as approved_by_name', (**This is the issue please help**)
DB::raw("case when job_postings.status = 0 then 'Pending' else 'Approved' end status"),
)
->leftJoin('dealerships', 'job_postings.dealership_id', '=', 'dealerships.id')
->leftJoin('departments', 'job_postings.department_id', '=', 'departments.id')
->leftJoin('positions', 'job_postings.position_id', '=', 'positions.id')
->leftJoin('users', 'job_postings.created_by', '=', 'users.id', 'job_postings.approved_by', '=', 'users.id')
->where('job_postings.id', $jp_id)
->get();
$data = [];
foreach($job_postings as $j => $job_posting){
$data[] = [
'job_posting_id' => $job_posting->job_posting_id,
'dealership_name' => $job_posting->dealership_name,
'department_name' => $job_posting->department_name,
'position_name' => $job_posting->position_name,
'qualifications' => $job_posting->qualifications,
'status' => $job_posting->status,
'created_by' => $job_posting->created_by_name,
'approved_by' => $job_posting->approved_by_name,
'created_at' => $job_posting->created_at->format('D, d M Y').date(' | h:i A', strtotime($job_posting->created_at)),
'updated_at' => $job_posting->updated_at->format('D, d M Y').date(' | h:i A', strtotime($job_posting->updated_at)),
];
}
Under the last leftJoin
->leftJoin('users', 'job_postings.created_by', '=', 'users.id', 'job_postings.approved_by', '=', 'users.id')
the approved_by is a foreign key pointing to users id and created_by is also a foreign key pointing to users id.
What I am aiming at is to get the name of the user but in separate reference.
Somewhat similar to this analogy .
'users.name = created_by as created_by_name',
'users.name = approved_by as approved_by_name',
approved_by = user.id => user.name
created_by = users.id => user.name
Thanks.
leftJoin('users','job_postings.created_by','=','users.id', 'job_postings.approved_by', '=', 'users.id')
Try this,
->leftJoin('users', function($join){ $join->on('users.id', '=', 'job_postings.created_by'); $join->on('users.id', '=', 'job_postings.approved_by'); })
I have a query in which I need to add a column (is_found) on the base of another table "history", if product_id exists on a table "history" then the column value (is_found) became 1 otherwise its value remains 0.
Here is my query:
Product::select(
'products.id as product_id',
'products.name',
'products.desc',
'products.image',
'products.barcode',
'categories.name as category_name',
'categories.id as category_id',
)
->leftJoin(
'categories',
'products.category_id',
'=',
'categories.id'
)
Try this:
Product::select(
'products.id as product_id',
'products.name',
'products.desc',
'products.image',
'products.barcode',
'categories.name as category_name',
'categories.id as category_id',
\DB::raw('IF(history.product_id, 1, 0) AS is_found')
)
->leftJoin(
'categories',
'products.category_id',
'=',
'categories.id'
)
->leftJoin('history', 'products.id','=','history.product_id')
Or:
Product::select(
'products.id as product_id',
'products.name',
'products.desc',
'products.image',
'products.barcode',
'categories.name as category_name',
'categories.id as category_id',
\DB::raw('IF((select product_id from history where history.product_id = products.id), 1, 0)')
)
->leftJoin(
'categories',
'products.category_id',
'=',
'categories.id'
);
You can use sub-select with exists
Product::select(
'products.id as product_id',
'products.name',
'products.desc',
'products.image',
'products.barcode',
'categories.name as category_name',
'categories.id as category_id',
)
->selectRaw('exists (select * from history where history.product_id = products.id) as is_found')
->leftJoin('categories', 'products.category_id', '=','categories.id')
I am having some trouble in Laravel using the query builder to select users based on two where clauses.
The first where clause would contain multiple where statements to select a user based on some conditions. If this fails in the OR part I would like to check simply if the user ID is in the array.
Would be grateful for some advice on how I could achieve this.
Thanks.
$rs = DB::table('tblUser')
->select('name')
->where(function($q) {
$q->where(function($q){
$q->where('fid', '=', $this->argument('fid'))
->where('type', '<', 10)
})
->orWhereIn('id', $userIdSArray);
})
->get();
$userIdSArray = [ '2', '4', '5' ];
$rs = DB::table( 'Users' )
->select( 'name' )
->where( function ( $q ) use ( $userIdSArray ) {
$q->where( function ( $q ) {
$q->where( 'fid', '=', $this->argument( 'fid' ) )
->where( 'type', '<', 10 );
})
->orWhereIn( 'id', $userIdSArray );
})
->get();
I think you need to pass $userIdSArray in Query builder . And You also forgot (;) after [->where( 'type', '<', 10 )]
I have a question i have 4 tables
Deals
Lists
Lists_Galleries
List_has_deals
Lists_has_gallery
I need to obtain the img_src_list what is in the List_Galleries but from deals.
I have this var in this time
$query = ListsDeals::where( $matchDeals )
->where('stock', '>', 0)
->orwhere( $matchOtherDeals )
->whereDate('end_date', '>', date('Y-m-d'))
->limit( 4 )
->offset( 0 )
->orderBy( 'start_date' );
$deals = $query->join( 'list_has_deals', 'deals.id', '=', 'list_has_deals.deal_id' )
->join( 'lists', 'list_has_deals.list_id', '=', 'lists.id' )
->join( 'list_has_gallery', 'lists.id', '=', 'list_has_gallery.list_id' )
->join( 'lists_galleries', 'list_has_gallery.gallery_id', '=', 'lists_galleries.id' )->get();
This Give me the results but how i have the same name in all tables for example title for deals and lists that overwrite the names and dont get the values correct, how i can obtain certain columns without overwrite the others? regards.
UPDATE
This give me always the same deal for all results.
$deals = $query->join( 'list_has_deals', 'deals.id', '=', 'list_has_deals.deal_id' )
->join( 'lists', 'list_has_deals.list_id', '=', 'lists.id' )
->join( 'list_has_gallery', 'lists.id', '=', 'list_has_gallery.list_id' )
->join( 'lists_galleries', 'list_has_gallery.gallery_id', '=', 'lists_galleries.id' )
->select([ 'deals.id as deal_id', 'deals.stock as stock', 'deals.price as price', 'deals.price_reduced as price_reduced', 'deals.img_src as img_src', 'deals.title_deal as deal_title' ])->get();
UPDATE
$deals = $query->join( 'list_has_deals', 'deals.id', '=', 'list_has_deals.deal_id' )
->join( 'lists', 'list_has_deals.list_id', '=', 'lists.id' );
$other = $deals->join( 'list_has_gallery', 'lists.id', '=', 'list_has_gallery.list_id' )
->join( 'lists_galleries', 'list_has_gallery.gallery_id', '=', 'lists_galleries.id' )
->select([ 'deals.id', 'deals.stock', 'deals.price', 'deals.price_reduced', 'deals.img_src', 'deals.title_deal', 'lists_galleries.img_src_list' ])
->addSelect([ 'lists_galleries.img_src_list' ])
->get();
You can use select() to choose only those columns you want, and use aliases to rename any that clash:
$query->select(['lists.title AS title', 'lists_galleries.name AS name', 'lists.id AS id'])->get();
That way you can cherry-pick only those columns you need and deal with clashes easily.
i have this
public function deals(){
$matchThese = [ 'suspended' => 0, 'status' => 1, 'approved' => 1 ];
$deals = ListsDeals::where( $matchThese )->orderBy( 'start_date' )->get();
$list = DB::table( 'lists' )
->join( 'list_has_deals', 'lists.id', '=', 'list_has_deals.list_id' )
->where( 'list_has_deals.deal_id', '=', 12)
->select( 'lists.id' )
->get();
$categories = DB::table( 'lists_categories' )
->join( 'list_has_categories', 'lists_categories.id', '=', 'list_has_categories.category_id' )
->where( 'list_has_categories.list_id', '=', $list[0]->id )
->select( 'lists_categories.title' )
->get();
return view( "deals" )
->with( "deals", $deals )
->with( "categories", $categories );
}
I want to obtain the value of title for the categories in lists, but first i need to obtain the deals for the lists in less words
I have
Deals - Lists - lists_has_deals
Categories - Lists - lists_has_deals
Both are belongsToMany, i want obtain in the deals the categories belonging to the list that is associated with the offer.
In my example that works fine but the 12 need to be a foreach of the $deals not be number static, thanks for the help.
Try using a has many through or intermediate pivot table on lists_has_deals. If I'm understanding your question, lists should have the necessary reference to both deals and categories.
https://laravel.com/docs/5.4/eloquent-relationships#has-many-through
https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
specifically withPivot()