Hey guys I´ve got a simple question, I'm doing some math operations on a selectRaw query, but i need to round down the results (for example with floor()). How can I do this on my selectRaw query?
$primer = DB::connection('lab_inv')
->table('products')
->join('primer_adaptor', 'products.id', 'primer_adaptor.Product_id')
->selectraw('primer_adaptor.Product_id, primer_adaptor.Primer_Name,
primer_adaptor.Amount / primer_adaptor.Amount_Run AS Amount,
products.Amount / (products.Amount_Run * products.Runs_week) AS Runs, (products.Runs / products.Runs_week) * 5 AS Running_days')
->get();
Your may just use MySQL's FLOOR function as you typically would in a raw MySQL query, e.g.
$sql = "pa.Product_id, pa.Primer_Name, pa.Amount / pa.Amount_Run AS Amount, ";
$sql .= "FLOOR(p.Amount / (p.Amount_Run * p.Runs_week)) AS Runs, ";
$sql .= "(products.Runs / products.Runs_week) * 5 AS Running_days";
$primer = DB::connection('lab_inv')
->table('products AS p')
->join('primer_adaptor AS pa', 'p.id', 'pa.Product_id')
->selectraw($sql)
->get();
Here I have just taken the floor of the alias you named "Runs," but you may use FLOOR wherever you want.
Related
I am looking for a solution to filte jobs basing on the salary.
I have a Job model which has 2 column min_salary and max_salary, and the user is going to use a slider to pick two values as min and max salary.
I have tried the whereBetween and orWhereBetween but the problem is the query gets closed and I can't proceed with other filters, so am trying to get the average between the model min/max salary and use it instead of the two slaries.
Here's what i tried:
$salary = explode(',',$request->salary); // geting the salary range from the request as array
$jobs = Job::whereBetween('min_salary',$salary)->orWhereBetween('max_salary',$salary);
This solution does not work as I want, as I can't proceed with other filters.
I also tried to do a custom orWhere function and do seperated whereBetween queries, but I got the same result.
What I am trying now is to get the average between the model max and min salary without creating another field*, and then proceed to do something like that :
$jobs = Job::whereBetween('theCalculatedAvg',$salary);
I appreciate any help with any kind of solution that does not require creating another field in the database, and i wont mind an sql raw solution if it does the job.
Thank you.
Update
Heres the whole function u had :
if($request->has('offset')) {
$salary = explode(',',$request->salary);
$jobs = Job::whereBetween('min_salary',$salary)->orWhereBetween('max_salary',$salary);
if ($request->has('lat')) {
$sqlDistance = DB::raw
('
( 6371 * acos
( cos
( radians
(' . $request->lat . ')
)
* cos
( radians
( lat )
)
* cos
( radians
( lon )
- radians
(' . $request->lon . ')
)
+ sin
( radians
(' . $request->lat . ')
)
* sin
( radians
( lat )
)
)
)
');
$jobs->when($sqlDistance != null, function ($query) use ($sqlDistance,$request){
$query->whereHas('address', function ($subQuery) use ($sqlDistance,$request) {
$subQuery->addSelect(DB::raw("{$sqlDistance} AS distance"));
$subQuery->havingRaw("distance <= ?", [(int)$request->range]);
});
})
->with('company')
->with('address');
}
if ($request->has('key')) {
$jobs->where('title', 'like', '%' . $request->key . '%');
}
if ($request->has('cat')) {
$cat = explode(',',$request->cat);
$jobs->whereIn('category_id', $cat);
}
if ($request->has('type')) {
$type = explode(',',$request->type);
$jobs->whereIn('type', $type);
}
if($request->has('hs')) {
return view("General::browseJobs", [
'jobs' => $jobs->orderBy('created_at','desc')->skip($request->offset * 2)->take(2)->get(),
'count' => count($jobs->get())
]);
}
$view = view('General::loaders.jobs', [
'jobs' => $jobs->orderBy('created_at','desc')->skip($request->offset * 2)->take(2)->get()
])->render();
return response()->json(['html' => $view , 'count' => count($jobs->get()) ]);
}
return view("General::browseJobs", [
'jobs' => Job::orderBy('created_at','desc')->take(2)->get(),
'count' => count(Job::all())
]);
The issue is that i just want the salary filter to work this way:
lets say the user picked twho values : $min and $max (will be stored in an array)
now i want to show him the jobs where the min_salary is between [$min, $max]
or the max_salary is between [$min, $max].
NB : if i use :
Job::whereBetween('min_salary',$salary)->whereBetween('max_salary',$salary);
without the or it works just fine, but i want the or logic to be implemented.
You need to scope the or to those 2 conditions only:
Jobs::where(function ($q) use ($salary) {
$q->whereBetween('min_salary',$salary)->orWhereBetween('max_salary',$salary);
})
To understand why this is required, you need to consider the sql query produced by eloquent.
If you write:
$jobs = Jobs::where([condition1])->orWhere([condition2]);
.. some other code..
$jobs->where([condition3]);
...
$jobs->where([condition4]);
The resulting query will be:
SELECT *
FROM jobs
WHERE [condition1] OR [condition2] AND [condition3] AND [condition4]
But in SQL, the AND operator has precedence over the OR, so the conditions are logically considered like this:
([condition1]) OR ([condition2] AND [condition3] AND [condition4])
This is not the behavior you want.
By scoping the OR condition in a where closure, you basically tell eloquent to add a parenthesis around the conditions, so:
$jobs = Jobs::where(function ($q) {
$q->where([condition1])->orWhere([condition2]);
});
.. some other code..
$jobs->where([condition3]);
...
$jobs->where([condition4]);
Results in the following query:
SELECT *
FROM jobs
WHERE ([condition1] OR [condition2]) AND [condition3] AND [condition4]
which is the desidered one
Ok, thank you for updating the question. I'm pretty sure I'm not able to answer it in one go, but I'll do my best.
As far as I can see, you are working on a Job site where you want to allow users to enter filters, and only show jobs matching those filters.
I see you have filters for min/max salary, distance, title, categories and types.
You also have a hs key which decides which view to open with which data.
I would consider the min/max salary to be an OR statament, and the rest an AND.
In that case I would do
$mainQuery = Job::where(function($query) use($salary)
{
$query->whereBetween('min_salary', $salary)->orWhereBetween('max_salary', $salary);
});
So you can do $mainQuery->where('anothermust-have', $somevalue);
In my code, i am querying a database by accepting month and year input from user.
I have tried writing it the normal PHP way and other ways i can find online but none seems to be working. here is the code i am using currently
$salesmonth = $request->input('mn');
$salesyear = $request->input('yr');
$id = Auth::user()->id;
$comm = \DB::table('bakerysales')
->where([
['customer_id', '=', $id], [MONTH('sales_date'), '=', $salesmonth], [YEAR('sales_date
'), '=', $salesyear]
])
->get();
return view::make('showCommission')->with('comm', $comm);
I expect the query to return data from rows that match user selected month and year
Laravel comes with a few different where clauses for dealing with dates e.g.
whereDate / whereMonth / whereDay / whereYear.
This means that your controller method can look something like:
$comm = \DB::table('bakerysales')
->where('customer_id', auth()->id())
->whereMonth('sales_date', $request->input('mn'))
->whereYear('sales_date', $request->input('yr'))
->get();
return view('showCommission', compact('comm'));
I'm having the following function to calculate distances between two points using Haversine formula:
public static function getByDistance($distance)
{
$pubsFiltered = DB::select(
'SELECT * FROM
(SELECT *, (6371 * acos(cos(radians(40.4169473)) * cos(radians(latitude)) *
cos(radians(longitude) - radians(-3.7035285)) +
sin(radians(40.4169473)) * sin(radians(latitude))))
AS distance
FROM pubs) AS distances
WHERE distance < ' . $distance . '
ORDER BY distance
;
');
return $pubsFiltered;
}
This is returning an array instead of a collection, that is what I need.
If I change DB to Pub it returns an error because of the subquery where I calculate "distance" using my table "pubs".
How can I change the whole function or simply the subquery to have an instance of my Pub model?...Do I have to use set/declare variables in mysql?
Thanks a lot!!
$pubs = Pubs::hydrate($pubsFiltered)
For now, I am using this query to obtain nearby records:
public function scopeNearby($query, $lat, $long, $distance = 10)
{
if($lat AND $long) {
// 3959 for miles, 6371 for kilometers
$distanceQuery = '(6371 * acos(cos(radians(?)) * cos(radians(geo_lat)) * ' .
'cos(radians(geo_long) - radians(?)) + sin(radians(?)) ' .
'* sin(radians(geo_lat))))';
return $query->select('*', DB::raw("{$distanceQuery} as distance"))
->addBinding([$lat, $long, $lat], "select")
->whereNotNull('geo_lat')
->whereNotNull('geo_long')
->whereRaw("{$distanceQuery} < ?")
->addBinding([$lat, $long, $lat, $distance], "where")
->orderBy('distance', "ASC");
}
}
You may notice that I have used the $distanceQuery for both SELECT and WHERE clauses. I am currently having issues when this scope is used alongside with the paginate() method. This might need some refactoring, but for now you can do the same.
I wrote a query with codeigniter, and need to unescape subquery in from() method. I have a complex query, here I simplify for you
$this->db->from("(SELECT * FROM acme WHERE CONCAT(',', RTRIM(rule), ',') LIKE '%,PER_UNIT,%') AS acme_filtered")
become:
SELECT * FROM (SELECT * FROM acme WHERE CONCAT(',', RTRIM(rule), ',') LIKE '%,`PER_UNIT`,%') AS acme_filtered
the part LIKE '%,PER_UNIT,%' turns into
LIKE '%,PER_UNIT,%'
data cannot be found because additional character (`) wraps the string. How to remove this character so the query turn right?
You could do this, but I don't know the implications of it, as it defeats the escaping system.
Use it with care!
$this->db->from("(SELECT * FROM acme WHERE CONCAT(',', RTRIM(rule), ',') LIKE '%,PER_UNIT,%') AS acme_filtered");
// the rest of your "complex query" code here
$query = $this->db->get_compiled_select();
$query = str_replace('%, `', '%,', $query);
$query = str_replace('`, %', ',%', $query);
$result = $this->db->query($query);
I'm trying to group my entity by a field (year) and do a count of it.
Code:
public function countYear()
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('b.year, COUNT(b.id)')
->from('\My\Entity\Album', 'b')
->where('b.year IS NOT NULL')
->addOrderBy('sclr1', 'DESC')
->addGroupBy('b.year');
$query = $qb->getQuery();
die($query->getSQL());
$result = $query->execute();
//die(print_r($result));
return $result;
}
I can't seem to say COUNT(b.id) AS count as it gives an error, and
I do not know what to use as the addOrderby(???, 'DESC') value?
There are many bugs and workarounds required to achieve order by expressions as of v2.3.0 or below:
The order by clause does not support expressions, but you can add a field with the expression to the select and order by it. So it's worth repeating that Tjorriemorrie's own solution actually works:
$qb->select('b.year, COUNT(b.id) AS mycount')
->from('\My\Entity\Album', 'b')
->where('b.year IS NOT NULL')
->orderBy('mycount', 'DESC')
->groupBy('b.year');
Doctrine chokes on equality (e.g. =, LIKE, IS NULL) in the select expression. For those cases the only solution I have found is to use a subselect or self-join:
$qb->select('b, (SELECT count(t.id) FROM \My\Entity\Album AS t '.
'WHERE t.id=b.id AND b.title LIKE :search) AS isTitleMatch')
->from('\My\Entity\Album', 'b')
->where('b.title LIKE :search')
->andWhere('b.description LIKE :search')
->orderBy('isTitleMatch', 'DESC');
To suppress the additional field from the result, you can declare it AS HIDDEN. This way you can use it in the order by without having it in the result.
$qb->select('b.year, COUNT(b.id) AS HIDDEN mycount')
->from('\My\Entity\Album', 'b')
->where('b.year IS NOT NULL')
->orderBy('mycount', 'DESC')
->groupBy('b.year');
what is the error you get when using COUNT(b.id) AS count? it might be because count is a reserved word. try COUNT(b.id) AS idCount, or similar.
alternatively, try $qb->addOrderby('COUNT(b.id)', 'DESC');.
what is your database system (mysql, postgresql, ...)?
If you want your Repository method to return an Entity you cannot use ->select(), but you can use ->addSelect() with a hidden select.
$qb = $this->createQueryBuilder('q')
->addSelect('COUNT(q.id) AS HIDDEN counter')
->orderBy('counter');
$result = $qb->getQuery()->getResult();
$result will be an entity class object.
Please try this code for ci 2 + doctrine 2
$where = " ";
$order_by = " ";
$row = $this->doctrine->em->createQuery("select a from company_group\models\Post a "
.$where." ".$order_by."")
->setMaxResults($data['limit'])
->setFirstResult($data['offset'])
->getResult();`