Eloquent get average for both genders from a collection without requesting again the database - laravel

I have this situation where I get a collection directly from the database and have introduced several filters already, except gender, as follows:
$workers = Worker::where('status','Active')->where('category','SomeCategory')->get();
In order to get the general age average, I get it like this:
$avg_age = $workers->avg('age');
So far so good.
Inside, the $workers collection, there is this column gender. Now I want to get the age average by gender. I have tried the following ... which doesn't work:
$avg_age_women = $workers->where('gender','female')->avg();
But this does not work since the returned value is zero.
I know I could do the same like:
$workers_female = Worker::where('status','Active')->where('category','SomeCategory')->where('gender','female')->get();
But, if I can continue working with the $workers collection, I think that'd be more efficient.
Is there a way to get the average of female ones right from the original $workers collection??? What am I missing?

You're not saying what you want to do avg on.
$avg_age_women = $workers->where('gender','female')->avg("age");

Related

How to get the matching data from two tables?

I'm used to compare 2 data, one data has an id and the other data is the one that needs comparing to get the matching datas. see code below.
DB::table('requests')->where('reqItem',$inventory->invItem)->get();
The code shown above displays all requests information that equals to the compared inventory item.
Now what i want to do now is to compare 2 tables without any id (ex. $inventory->invItem). I don't know how to ask this question but i hope you get what i mean. The figure below shows the way i wanted it to be.
You can run this query. Here, 'inventory' is the name of second table (change it accordingly)
DB::table('requests')
->join('inventory', 'requests.reqItem', '=', 'inventory.invItem')
->select('inventory.reqItem')
->get();

Make a group by with a where in statement Laravel

I am writing a little script to load an Attendee_logs, based that counts the total of prints for based on the hour.
First I load the id's from the attendees
$allAttendees->pluck('id')->implode(',')
So I get 389832, 321321 from this (this are the id's from the attendees, based on a group).
Now I want to group them by the hour.
But I cannot find out how I add the whereIn statement
$badgesPrintedByDate = DB::table('Attendee_logs')->select(DB::raw('hour(created_at)'), DB::raw('COUNT(id)'))->whereIn('id', [$allAttendees->pluck('id')->implode(',')])->groupBy(DB::raw('hour(created_at)'));
When I do it like this, I get an empty result.
But when I remove the whereIn I get a result.
So my question, How can I count the rows based on the Hour and where I also give the ID's with it :)?
I think this is gonna work:
$badgesPrintedByDate = DB::table('Attendee_logs')->select(DB::raw('hour(created_at)'), DB::raw('COUNT(id)'))->whereIn('id', $allAttendees->pluck('id')->all())->groupBy(DB::raw('hour(created_at)'));
Instead of saying:
$allAttendees->pluck('id')->all()
Which returns an array of ids, you can also say:'
$allAttendees->pluck('id')->values()
Or:
$allAttendees->pluck('id')->toArray();

Sum of the values of a particular user for a particular month of a particular year

I have a table with time stamp, user id, value. I am trying to get sum of the values of a particular user for a particular month of a particular year. This is what I am using:
$data = Laborhrs::all()->where('employee','7')->sum('value');
This is giving me sum of whole data for employee#7. I am looking to get sum of a particular month of a particular year. Say Sum of values of October 2018. What am I missing?
You forgot to add a condition for the year and month, and you don't need to use all() method.
$sum = Laborhrs::where('employee','7')
->whereMonth('timestamp_column_name', 10)
->whereYear('timestamp_column_name', 2018)
->sum('value');
In addition: I saw your several posts, and I think, you don't understand how laravel eloquent and collections work.
All() method returns collection with all results from database, and then you filters them trough collection (I saw it not first time). It is very slow solution.
Better to use conditions with get() (get() should go after conditions), for example:
$data = Laborhrs::where('employee','7')->get();
It will return collection with results that you need, and you don't need to filter them after getting from database. It will be work much faster.
In that situtation you don't need all() and get() methods at all. Eloquent has sum() method, that will calculate sum in database and return value.

Use ParseQuery to get the first item found from list

I want to query Parse in order to retrieve the first object found in a given list, in the given list's order.
My code looks pretty much like this:
query = getQuery(MyClass.class).whereContainedIn("FieldName", itemList);
networkQuery.getFirstInBackground(...);
What I need, specifically, is to retrieve the first item found in the list, meaning that if I provide it a list of numbers in ascending order, I wish to retrieve the object corresponding with the smallest number possible.
I'm not sure this is how getFirstInBackground() works, I know it fetches a single result, but how can I assure the search is made according to the order of the list I provided as argument?
You have to order your query using the -orderByAscending (or Descending, i can't remember) method. It takes the column name parameter.
So something simple and easy to understand (but I'm sure you've understood already) is to order by ascending "Age" (example), and your first result in the array will be the smallest Age.
Once your query is ordered, just set a -limit to it. It's the number of results the query will return, if you only want the five firsts, set a limit of 5. or 20. The maximum is 1000.
If you also would like to skip the 3 first results because you know they're not interesting (and I'm just elaborating out of your question's scope here), you can use the -skip method, to skip the first X results.
This should do the trick to build your query. Set all those parameters and then execute your query and you'll have correct results.
EDIT : After re-reading your question I'm not sure I'm answering what you're asking. Please elaborate if I'm not.
Find the minimum value in itemList yourself, and qualify the query with that using equalTo.
// is this javascript? if so, underscorejs is very useful
var _ = require('underscore');
var minItem = _.min(itemList); // you can add an optional iteratee function that can minimize any computation over the list
query.equalTo("FieldName", minItem);
query.getFirstInBackground(...);
Edit
Parse.Query ordering applies only to sortable types, like strings and numbers. The ordering hoped for in the question is on the min() value of an array attribute. If such a thing were available, then a getFirst query would work.
What you need can still be done with find(). Since a small number of rows will have FieldName values contained in itemList, you can just do a find() and pick out the minimum from those few results...
query.find().then(function(results) {
return _.min(results, function(result) {
return result.get("FieldName");
});
});

Going .pluck crazy. What is a realistic limit on query with array

I've used .pluck(:id) quite often (and map before it) to get a set of record ids. This is usually to get a set of related model records (e.g,, :people has_many :scores, as :assessed)
Lets say I have 10,000 people, but a query on People limits it to say 1,000.
people_ids = people.pluck(:id) #people a relation/scoped
scores = Score.where(:assessed_type => 'People', :assessed_id => people_ids)
There would be more to the Score query, but my basic question is querying with an array of say 1000 ids a bad idea?
I should point out that the filtered Score query would be used to get a new set of People. This is a filter on People.
I only have a few hundred records in my test DB, and that works fine - but there must be a point where psql or Rails is going to blow up. In production, I don't see going more that 1000 ids since People is automatically filter before this Score option is used.

Resources