how to add conditional where clause in sql - mysql

Looking for improved answer
In Laravel, I am using a raw query. My question is how to add where clause depending on variable value
i.e. if $cid is present then the query should be
select * from user where aid=2 and cid=1;
If it is not present
select * from user where aid=2;
Ideally, I can do it like this
if($cid) {
$query = DB::select("select * from user where aid=2 and cid=1");
} else {
$query = DB::select("select * from user where aid=2");
}
Is there any way to do this without the above method?

This can be achieved with conditional clauses.
$users = DB::table('users')
->where('aid', 2)
->when($cid, function ($query) {
$query->where('cid', 1);
})
->get();

Please contextualize your question well, we don't know what kind of condition you are talking about, nor in what sense your question is asked.
normally the comment above would be enough but it is necessary to specify
Here are some examples from the documentation
$users = DB::table('users')
->where('votes', '=', 100)
->where('age', '>', 35)
->get();
$users = DB::table('users')->where('votes', 100)->get();
You may also pass an array of conditions to the where function. Each element of the array should be an array containing the three arguments typically passed to the where method:
$users = DB::table('users')->where([
['status', '=', '1'],
['subscribed', '<>', '1'],
])->get();
I encourage you to read the documentation which is very clear on this subject and to come back to me in case of misunderstanding
here

Related

Optimize Laravel Query

please someone can optimize this query according to Laravel query builder with some help of joins
Product::select(DB::raw('
products.*
,(select name from users where users.id=products.user_id) as user_name
'))
->where(function ($query) use ($searchKey) {
if (trim($searchKey) != '') {
$query->where('name', 'like', '%' . trim($searchKey) . '%');
}
})
->orderBy($orderBy,$orderType)
->paginate(10)
Maybe something like this:
//Start your query as usual, but just join the user data in. Do not use paginate function yet as this will trigger the query to execute.
$productQuery = Product
::selectRaw('products.*, users.name as user_name')
->join('users', 'users.id', 'products.user_id')
->orderBy($orderBy, $orderType);
//Check (for each param) if you want to add where clause
//You dont need to nest the where function, unless you have more filters, and need to group statements together
if(!empty(trim($searchKey))) {
$productQuery->where('name', 'like', '%' . trim($searchKey) . '%');
}
//Execute query
$products = $productQuery->paginate(10);
Note that the query builder only touches the db with specific functions like chunk, get, first or paginate(there are more). When building the query, you have full freedom of adding filters/ordering/grouping untill you execute the query.
I hope it helps, please let me know if it worked for you.

Proper Way of Formatting Where Clause with Alias - Laravel

I'm stuck on an issue that I'm not quite sure how to properly reformat. Below are the relevant portions of a controller function:
$paidQuery = DB::table('shipments')
->leftJoin('customers', 'shipments.bill_to', '=', 'customers.id')
->leftJoin('customer_addresses', 'shipments.billerLocation', '=', 'customer_addresses.id')
->leftJoin('payments_distributions','shipments.id','=','payments_distributions.shipment_id')
->select('shipments.*', 'customers.customer_name','customer_addresses.billingMethod',DB::raw('COALESCE(sum(payments_distributions.amount),0) AS paid'));
$paidQuery->where('shipments.shipment_origin', 1);
$paidQuery->where('shipments.balance', '<', 'paid')
->where('shipments.balance','>', 0)
->whereNotIn('shipments.shipment_billing_status', [2,3,5]);
if(!empty($_GET['startDate']) || !empty($_GET['endDate'])){
$paidQuery->where(function($query) {
if(empty($_GET['startDate'])){
$startDate = Carbon::create(1900, 1, 1, 0, 0, 0);
} else {
$startDate = $_GET['startDate'];
}
if(empty($_GET['endDate'])){
$endDate = Carbon::now();
} else {
$endDate = $_GET['endDate'];
}
return $query->whereBetween('date', [$startDate, $endDate])
->orWhereNull('date');
});
}
$paidQuery->whereNull('shipments.deleted_at')
->orderBy('shipments.pro_number', 'DESC')
->groupBy('shipments.id')
->limit(100);
Now, as you can see above, there is a select statement (5th line), where at the end is an alias. This is there solely as an example of how the data that I get is returned. I've used it to verify what is and isn't working and that specific line works, the part that doesn't work is this line:
$paidQuery->where('shipments.balance', '<', 'paid')
What would be the proper way to get the sum (or zero (0)) of all of the amount from the payments_distributions table where the record IDs are the same?
I have been looking around and can't find an appropriate example what I am looking for, but am certain it is more likely the search terms or phrasing.
Thanks.
It isn't possible in MySQL to use an alias defined in a select clause in a where clause, at the same level. But, MySQL overloaded the HAVING operator to allow aliases to be used, so the following should work here:
$paidQuery = DB::table('shipments')
->leftJoin('customers', 'shipments.bill_to', '=', 'customers.id')
->leftJoin('customer_addresses', 'shipments.billerLocation', '=', 'customer_addresses.id')
->leftJoin('payments_distributions','shipments.id','=','payments_distributions.shipment_id')
->select('shipments.*', 'customers.customer_name','customer_addresses.billingMethod',DB::raw('COALESCE(sum(payments_distributions.amount),0) AS paid'));
$paidQuery->where('shipments.shipment_origin', 1);
$paidQuery->having('shipments.balance', '<', 'paid');
$paidQuery->where('shipments.balance', '>', 0)
$paidQuery->whereNotIn('shipments.shipment_billing_status', [2,3,5]);
To be clear here, I am suggesting that you use the following raw MySQL:
HAVING paid > shipments.balance

Laravel Query Builder - where clause equals anything programmatically

I'm using Laravel 5.6 - Query Builder.
Is it possible to make a query builder where statement that a value equals everything programmatically?
Let's say that I have this code:
$foo = 1;
DB::table('users')
->select('*')
->where('status', '=', $foo)
->get();
If $foo = 1 then it's straightforward. The query will select everything with the status of 1.
Q: Is it possible to assign something to the $foo variable so the select query returns every record regardless of the status from the DB?
Of course, I can make it happen with 2 query statements like this:
$foo = 1;
if ($foo === null) {
DB::table('users')
->select('*')
->get();
} else {
DB::table('users')
->select('*')
->where('status', '=', $foo)
->get();
}
However, I'm looking for a shorter / more effective solution. Is it possible somehow - without using raw code inside the Where statement?
You may try something like this:
$query = DB::table('users')->select('*');
// $foo = 'get it...';
if ($foo) {
$query->where('status', $foo);
}
$result = $query->get();
Or even more laravel-ish:
$result = DB::table('users')->select('*')
->when($foo, function ($query) use ($foo) {
return $query->where('status', $foo);
})
->get();
Check more here.

Laravel 5.4 Raw Join Query

I have a table TBL_POST used to store blog posts. A post can be assigned to multiple categories, there is a column, cat_id that stores category ID's in comma separated pattern like 2,4,6. I want to use FIND_IN_SET() method in this line
->leftJoin(TBL_CAT.' as c', 'p.cat_id', '=', 'c.id')
to show the associated category names. How can I do that?
public static function getPostWithJoin($status="")
{
$query = DB::table(TBL_POST .' as p')
->select('p.id','p.post_title','p.post_status','u.name as author','c.name as cat_name','p.updated_at')
->leftJoin(TBL_ADMINS.' as u', 'p.post_author', '=', 'u.id')
->leftJoin(TBL_CAT.' as c', 'p.cat_id', '=', 'c.id')
->where('p.post_type','post');
if($status!="all") {
$query->where('p.post_status',$status);
}
$query->orderby('p.id','DESC');
$data = $query->paginate(20);
return $data;
}
You can use callback to create more complicated join query.
->leftJoin(TBL_CAT, function($query){
$query->on(TBL_CAT.'id', '=', 'p.cat_id')->where("**", "**", "**");
})
Here is link on laravel doc - https://laravel.com/docs/5.4/queries#joins "Advanced Join Clauses" section.
UPD::
As mentioned in comment it is not good idea to have string for such types of data. Cause search by equality should be much simpler than string check. Even if your amount of data should not have big difference, you never know what will happen with your app in future.
But if you still want to do that i think you can try like this
->leftJoin(TBL_CAT, function($query){
$query->where(DB::raw("FIND_IN_SET(".TBL_CAT.".id, p.cat_id)"), "<>", "0");
})
Join that will check existence of id in cat_id.

How add to collection only models with no record joined - Eloquent

In my model Questions I have simple relation to Standpoint
public function standpoints_byrel()
{
// return $this->hasMany('App\Models\Standpoint');
return $this->hasMany('App\Models\Standpoint', 'question_id');
}
Now,
I have yet another model Userattitude (tableuser_attitudes`) which allow users to upvote and downvote Standpoints.
I am able to list Standpoints, which were voted by a given user:
$user_attitudes = Userattitude::join('entitystandpoints', function ($q) use($questionid,$user) {
$q->where('user_attitudes.item_type', '=', 'entitystandpoint');
$q->on('user_attitudes.item_id', '=', 'entitystandpoints.id');
$q->where('entitystandpoints.question_id', '=', $questionid);
$q->where('user_attitudes.creator_id','=', $user);
})
->select('user_attitudes.*')
->get();
TO DO
Now I try to list all standpoints, which were NOT voted by the given user.
I have no idea how to do it using Eloquent.
Any help appreciated.
edit
condition to meet:
if an user votes up or down, a new model Userattitude is created. Therefore Standpoint models not down- or upvoted have nothing to join. still, in the Userattitude there are two fields for upvoting : 'attitude' and 'importance'. often one of them is null
Try with a left join where the left parameter of the join is null.
Something like this (but please check the syntax out, I'm not an Eloquent expert):
$user_attitudes = Userattitude::leftJoin('entitystandpoints', function ($q) use($questionid,$user) {
$q->where('user_attitudes.item_type', '=', 'entitystandpoint');
$q->on('user_attitudes.item_id', '=', 'entitystandpoints.id');
$q->where('entitystandpoints.question_id', '=', $questionid);
$q->where('user_attitudes.creator_id','=', $user);
})
->whereNull('entitystandpoints.id')
->select('user_attitudes.*')
->get();
Let me know.