Laravel - Multiple Where Queries - php

I'm trying to use multiple where queries on a sqlite database which are then only selected between two date ssDate and seDate. for some reason, I am having nothing returned when I know there is an entry in between two dates.
if($status == "newOngoingClosed"){
//dd($status, $ssDate, $seDate);
$selStatus = Account::where('cActive', '=', 'New')
->orWhere('cActive', '=', 'Ongoing')
->orWhere('cActive', '=', 'Closed')
->whereBetween ('refDate', [$ssDate, $seDate])
->get();
dd($selStatus);
return view('reports_active')->withDetails($selStatus)->withQuery($status);
}
any help would be greatly appreciated.

Instead of using multiple orWhere you can use whereIn to get the desired output:
$selStatus = Account::whereIn('cActive', ['New','Ongoing','Closed'])
->whereBetween ('refDate', [$ssDate, $seDate])
->get();

Your query currently is:
select *
from `accounts`
where `cActive` = ? or `cActive` = ? or `cActive` = ? and `refDate` between ? and ?
Notice that the last condition is and AND which means it will select things which are either new or ongoing or closed and between those dates
You need:
Account::where([
['cActive', '=', 'New','or'] ,
[ 'cActive', '=', 'Ongoing','or' ],
['cActive', '=', 'Closed','or']
])->whereBetween ('refDate', [Carbon::now(), Carbon::now()])->get() //Note the carbons are just date placeholders , you can use your own
This will execute:
select * from `accounts` where (`cActive` = ? or `cActive` = ? or `cActive` = ?) and `refDate` between ? and ?

Related

How to use where not between in Laravel 5.5?

I am try
ing to get something like this
select * from `users`
inner join `settings`
on `users`.`id` = `settings`.`user_id`
and NOW() NOT BETWEEN quit_hour_start AND quit_hour_end
where `notification_key` != ''
and `device_type` = 'Android'
in eloquent. Does anyone try and get success to build this query in eloquent.
I know I can use \DB::select(DB::raw()); and get my result. But I want to use ie with Laravel eloquent method.
====== update comment for tried queries========
$androidUser = User::join('settings', function ($join) {
$join->on('users.id', '=', 'settings.user_id')
->where(DB::raw("'$currentTime' NOT BETWEEN quit_hour_start AND quit_hour_end"));
})
->where('notification_key', '!=', '')
->where('device_type' ,'=', 'Android')
->get();
$users = DB::table('users')
->whereNotBetween('votes', [1, 100]) // For one column
->whereRaw("? NOT BETWEEN quit_hour_start AND quit_hour_end", [$currentTime]) // Use whereRaw for two columns
->get();
https://laravel.com/docs/5.5/queries, or you can rewrite as to wheres

using SUM in whereraw/where in laravel framework

I have columns named as PlanCost Discount AmountPaid and a label which contains the Due
Here,I am trying to display only the rows where the PlanCost != AmountPaid
this is my whole query
$getID = isset($inputArray['id']) ? $inputArray['id'] : 0;
$query = TelePlanSelect::join('tele_plan', 'tele_plan.id', '=', 'tele_plan_select.teleplan_id' )
->leftjoin('tele_payment_defs', 'tele_payment_defs.telereg_id', '=', 'tele_plan_select.telereg_id')
->leftjoin('tele_payment_items', function ($join){
$join->on('tele_payment_items.telepaymentdefs_id', '=', 'tele_payment_defs.id')
->on('tele_payment_items.teleplan_id', '=' ,'tele_plan.id');
} )
->selectRaw('tele_plan.id as `PlanID`,' .
'tele_plan.plan_name as `PlanName`,' .
'tele_plan.plan_cost as `PlanCost`,' .
'tele_plan.plan_details as `PlanDetails`,'.
'sum(tele_payment_items.amount) as `AmountPaid` ,'.
'COALESCE(sum(tele_payment_items.discount),0) as `Discount`,'.
'(COALESCE(tele_plan.plan_cost,0) - sum(COALESCE(tele_payment_items.discount,0))) - sum(coalesce(tele_payment_items.amount, 0)) as `Due` '
)
->where('tele_plan_select.telereg_id', $getID)
->groupBy('tele_plan.id')
->where(' tele_plan.plan_cost', '!=', 'sum(tele_payment_items.amount)');
I am not sure whether we can use sum in where/whereraw
Could someone help me?
EDIT 1 :
{"message":"SQLSTATE[HY000]: General error: 1111 Invalid use of group function (SQL: select count(*) as aggregate from (select tele_plan.id asPlanID,tele_plan.plan_name asPlanName,tele_plan.plan_cost asPlanCost,tele_plan.plan_details asPlanDetails,sum(tele_payment_items.amount) asAmountPaid,COALESCE(sum(tele_payment_items.discount),0) asDiscount,(COALESCE(tele_plan.plan_cost,0) - sum(COALESCE(tele_payment_items.discount,0))) - sum(coalesce(tele_payment_items.amount, 0)) asDuefromtele_plan_selectinner jointele_planontele_plan.id=tele_plan_select.teleplan_idleft jointele_payment_defsontele_payment_defs.telereg_id=tele_plan_select.telereg_idleft jointele_payment_itemsontele_payment_items.telepaymentdefs_id=tele_payment_defs.idandtele_payment_items.teleplan_id=tele_plan.idwheretele_plan_select.telereg_id= 8 and tele_plan.plan_cost <> sum(tele_payment_items.amount) group bytele_plan.id) as a) # C:\\xampp\\htdocs\\halframework\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php:625","status":"failed"}
You can use raw sql functions like sum, but you have to wrap them in laravel's \DB::raw() function so they won't be escaped.
For your Where clause, you should do the following
->where('tele_plan.plan_cost', '<>', \DB::raw('sum(tele_payment_items.amount)'));
You could also use laravel's WhereRaw function to write your own conditions:
->whereRaw('tele_plan.plan_cost <> sum(tele_payment_items.amount)')
Update:
The error stated that there was a problem with the GroupBy. The reason for this is because a sum can only be done after a group by, but a where can't. So, this will have to be added in a HAVING clause.
Replace the where by a having, and this should work:
->havingRaw('tele_plan.plan_cost <> sum(tele_payment_items.amount)');

convert SQL query to query builder style

Im trying days to understand how I can convert a SQL query to a query builder style in laravel.
My SQL query is:
$tagid = Db::select("SELECT `id` FROM `wouter_blog_tags` WHERE `slug` = '".$this->param('slug')."'");
$blog = Db::select("SELECT *
FROM `wouter_blog_posts`
WHERE `published` IS NOT NULL
AND `published` = '1'
AND `published_at` IS NOT NULL
AND `published_at` < NOW()
AND (
SELECT count( * )
FROM `wouter_blog_tags`
INNER JOIN `wouter_blog_posts_tags` ON `wouter_blog_tags`.`id` = `wouter_blog_posts_tags`.`tags_id`
WHERE `wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`
AND `id`
IN (
'".$tagid[0]->id."'
)) >=1
ORDER BY `published_at` DESC
LIMIT 10
OFFSET 0");
Where I now end up to convert to the query builder is:
$test = Db::table('wouter_blog_posts')
->where('published', '=', 1)
->where('published', '=', 'IS NOT NULL')
->where('published_at', '=', 'IS NOT NULL')
->where('published_at', '<', 'NOW()')
->select(Db::raw('count(*) wouter_blog_tags'))
->join('wouter_blog_posts_tags', function($join)
{
$join->on('wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->on('wouter_blog_posts_tags.post_id', '=', 'wouter_blog_posts.id')
->whereIn('id', $tagid[0]->id);
})
->get();
I have read that I can't use whereIn in a join. The error i now get:
Call to undefined method Illuminate\Database\Query\JoinClause::whereIn()
I realy dont know how I can convert my SQL to query builder. I hope when I see a good working conversion of my query I can understand how I have to do it next time.
This work for me:
DB::table('wouter_blog_posts')
->whereNotNull('published')
->where('published', 1)
->whereNotNull('published_at')
->whereRaw('published_at < NOW()')
->whereRaw("(SELECT count(*)
FROM wouter_blog_tags
INNER JOIN wouter_blog_posts_tags ON wouter_blog_tags.id = wouter_blog_posts_tags.tags_id
WHERE wouter_blog_posts_tags.post_id = wouter_blog_posts.id
AND id
IN (
'".$tagid."'
)) >=1")
->orderBy('published_at', 'desc')
->skip(0)
->take(10)
->paginate($this->property('postsPerPage'));
The following Query Builder code will give you the exact SQL query you have within your DB::select:
DB::table('wouter_blog_posts')
->whereNotNull('published')
->where('published', 1)
->whereNotNull('published_at')
->whereRaw('`published_at` < NOW()')
->where(DB::raw('1'), '<=', function ($query) use ($tagid) {
$query->from('wouter_blog_tags')
->select('count(*)')
->join('wouter_blog_posts_tags', 'wouter_blog_tags.id', '=', 'wouter_blog_posts_tags.tags_id')
->whereRaw('`wouter_blog_posts_tags`.`post_id` = `wouter_blog_posts`.`id`')
->whereIn('id', [$tagid[0]->id]);
})
->orderBy('published_at', 'desc')
->skip(0)
->take(10)
->get();
The subquery condition had to be reversed because you can't have a subquery as the first parameter of the where method and still be able to bind the condition value. So it's 1 <= (subquery) which is equivalent to (subquery) >= 1. The query generated by the above code will look like this:
SELECT *
FROM `wouter_blog_posts`
WHERE `published` IS NOT NULL
AND `published` = 1
AND `published_at` IS NOT NULL
AND `published_at` < Now()
AND 1 <= (SELECT `count(*)`
FROM `wouter_blog_tags`
INNER JOIN `wouter_blog_posts_tags`
ON `wouter_blog_tags`.`id` =
`wouter_blog_posts_tags`.`tags_id`
WHERE `wouter_blog_posts_tags`.`post_id` =
`wouter_blog_posts`.`id`
AND `id` IN ( ? ))
ORDER BY `published_at` DESC
LIMIT 10 offset 0
My process when creating more complex queries is to first create them and try them out in a SQL environment to make sure they work as indended. Then I implement them step by step with the Query Builder, but instead of using get() at the end of the query, I use toSql() which will give me a string representation of the query that will be generated by the Query Builder, allowing me to compare that to my original query to make sure it's the same.

running a mysql query containing division in laravel 5

I want to run this mysql query in Laravel 5 using the DB query :
// SELECT *, rating/number as total FROM `courses` order by total DESC;
This is what I tried :
$query = \DB::table('courses')->select('*');
$courses = $query->addSelect('rating/number as total')
->orderBY('total DESC')
->get();
but, rating/number is considered as a table column . The same thing happens when I tried it inside parenthesis (rating/number).
Any help?
$courses = \DB::table('courses')
->selectRaw('*, rating/number as total')
->orderBY('total', 'DESC')
->get();
Can you use Raw Expressions for it? Maybe something like this:
$courses = \DB::table('courses')
->select(DB::raw('*, (rating / number) as total'))
->orderBy('total DESC')
->get();

How do I use BETWEEN and AND in laravel

HI I am trying to use the following and not sure how to get this fixed
SELECT * FROM search_users
WHERE
match(first_name,last_name,country,city,location,nationality,short_bio)
against (?)
AND
search_users.loc_lng BETWEEN '-0.24272918701172' AND '-0.24272918701172'
AND
search_users.loc_lat BETWEEN '51.47026338272' AND '51.47026338272'
I am trying to write a laravel query that does exactly the same as
select * from search_users
where
......
and search_users.loc_lng BETWEEN '-0.24272918701172' AND '-0.24272918701172'
AND search_users.loc_lat BETWEEN '51.47026338272' AND '51.47026338272'
If you just want to build the query / get pure data without any logic around it, you can simply use the Query Builder:
$results = DB::table('search_users')
->where('first_name', $firstname)
->where('last_name', $last_name)
->where('country', $country) //and so on
->whereBetween('loc_lng', array(-0.24272918701172, -0.24272918701172))
->whereBetween('loc_lat', array(51.47026338272, 51.47026338272))
->get();
And sure enough you can use the same syntax if you're working with a Model:
$users = User::where('key1', $value1)
->where('key2', $value2)
->whereBetween('loc_lng', array(-0.24272918701172, -0.24272918701172))
->whereBetween('loc_lat', array(51.47026338272, 51.47026338272))
->get();
A little additional explanation concerning your question about how to use AND in eloquent:
AND is used by default if you use 2 or more where()s. So
DB::table('search_users')->where('first_name', $firstname)
->where('last_name', $last_name)
equals
SELECT * FROM search_users WHERE first_name = ? AND last_name = ?
For OR you can use orWhere():
DB::table('search_users')->where('first_name', $firstname)
->orWhere('last_name', $othername)
which equals
SELECT * FROM search_users WHERE first_name = ? OR first_name = ?
And sometimes you may need something more complicated, for instance:
SELECT * FROM search_users
WHERE first_name = ?
AND (last_name = ? OR last_name = ?)
AND age > 27
In Eloquent, this would be:
DB::table('search_users')
->where('first_name', $firstname)
->where(function($query) {
$query->where('last_name', $lastName1);
$query->orWhere('last_name', $lastName2);
})
->where('age', '>', 27)

Categories