what i am trying to do is to get distinct values (date) of my Model and for each date the display the corresponding data. When i make pagination of the distinct dates, it works fine, but in the pagination pages i see all the results instead of the distinct. Here is my function:
public function showdaily($id) {
$capacities = array();
// DB::enableQueryLog();
$capacity_daily = CapacityDaily::select('for_date')->where('capacity_id', '=', $id)->orderBy('for_date', 'asc')->distinct()->paginate(2);
// dd(DB::getQueryLog());
foreach($capacity_daily as $cap) {
$get_capacity = CapacityDaily::where('capacity_id', '=', $id)->where('for_date', '=', $cap->for_date)->orderBy('for_date', 'asc')->distinct()->get();
$capacities[] = array('for_date' => $cap->for_date, 'values' => $get_capacity, 'capacity' => Capacity::find($id)->first());
}
return view('admin.capacity.daily', compact('capacities', 'capacity_daily', 'id'));
}
I have totally 4 distinct dates and 96 rows in that table. As i want to display only 2 dates per page it should show me only one additional page available, but instead of that i have from 1-47.
What i make wrong ?
The toSql() method will show the query it is running, but I suspect you need to group on for_date rather than use distinct
$capacity_daily = CapacityDaily::select('for_date')->where('capacity_id', '=', $id)->orderBy('for_date', 'asc')->groupBy('for_date')->paginate(2);
Related
I want to use count and sum together on DB Query not sure how to go about it. I've tried several combinations but keep getting an error. I know I can just use a raw query but would like to learn how to use it correctly
Working:
DB::select('SELECT count(*) AS order_count, sum(total_including_vat)
AS orders_total FROM orders WHERE user_id =' .$userProfile->id);
Not Working
DB::table('orders')->where('user_id', '=', $userProfile->id)->count()->Sum();
count same as aggregates returns single value so
// you try to call method sum on number and it fails
DB::table('orders')->where('user_id', $userProfile->id)->count()->sum();
you can make two requests to get sum and count but its not a good idea, or get data in collection and let it do the math
// not a good idea
//$count = DB::table('orders')->where('user_id', $userProfile->id)->count();
//$sum = DB::table('orders')->where('user_id', $userProfile->id)->sum('total_including_vat');
//collection way
$orders = DB::table('orders')
->where('user_id',$userPorfile->id)
->get(['id', 'total_including_vat']);
$result = [
'order_count' => $orders->count(),
'orders_total' => $orders->sum('total_including_vat')
];
or the same result as for your working example with mix raw expressions
$result = DB::table('orders')
->where('user_id', $userProfile->id)
->selectRaw('count(1) as order_count, sum(total_including_vat) as orders_total')
->first();
Affiliate has many affiliatesHistory, affiliatesHistory belongs to affiliate, how to make the following query?
Take affiliates, where has affiliatesHistory, if affiliatesHistory records count is equal to 1, then do not take affiliatesHistory, which has status of uninstalled.
$affiliates = $user->affiliates()
->whereDoesntHave('affiliatesHistory', function ($q) {
$q->where('affiliates_histories.status', 'Installed earlier')
->orWhere('affiliates_histories.status', 'Uninstalled / Installed earlier');
The following query works, but I need to not take those affiliates, where affiliatesHistory count is equal to 1 and the status is uninstalled.
Any help will be appriaciated.
So, for what I understand you want to get the affiliates which affiliatesHistory status is Installed earlier. If this is the case then try this:
$user_affiliates = $user->affiliates();
$affiliates = $user_affiliates->whereHas('affiliatesHistory', function($q){
$q->where('status', 'Installed earlier');
})->get();
dd($affiliates);
For your case if there are more than one affiliatesHistory items then return else if there is only one affiliatesHistory then it should not contain Uninstalled status, I guess you can use conditional count to get desired results as
$affiliates = Affiliate::withCount([
'affiliatesHistory',
'affiliatesHistory as affiliatesHistoryUninstalled_count' => function ($query) {
$query->where('status', 'Uninstalled');
}
])->where('user_id', $user->id)
->havingRaw('affiliatesHistory_count > 1 OR (affiliatesHistory_count = 1 AND affiliatesHistoryUninstalled_count = 0)')
->get();
I have a simple eloquent query and want to include another table with my results, however, the order of relationship results is incorrect.
Is it possible to order the results without using an SQLRAW statement
$groups = AttributeGroup::with('attribute')->where('page_id', $page->id)->get();
What I would like -
$groups = AttributeGroup::with('attribute')->orderBy('iteration', 'DESC')->where('page_id', $page->id)->get();
I get the error of Unknown column because this column is part of relationship table.
This will order each attribute relation of every attribute group result:
$groups = AttributeGroup::with(['attribute' => function ($query) {
$query->orderBy('iteration', 'DESC');
}])->where('page_id', $page->id)->get();
Is this what you want to achieve?
You can use closures to change the query when using with and has.
$groups = AttributeGroup::with(['attribute' => function($query){
$query->orderBy('iteration');
})->where('page_id', $page->id)->get();
Details are available on https://laravel.com/docs/5.6/eloquent-relationships#constraining-eager-loads
I have a table called gk and I am currently running two queries. Please have a look at the queries:
Gk::groupBy(DB::raw("MONTH(created_at)"))
->groupBy(DB::raw("YEAR(created_at)"))
->selectRaw('id, user_id, sum(ton) as ton,pl, count(id) as total, sum(w) , created_at')
->with(array('user'=> function($q){
$q->select('id', 'userName', 'profilePic');
}))
->where('user_id', $userData[0]->id)
->get();
This query returns a little summary of every months. As you can I see I am grouping results by months and years. And I have another query which will return all the rows of any given months.
I am running second query like this
$m=Carbon::parse($request->date);
Gk::where('user_id',$request->user_id)->whereRaw(DB::raw("YEAR(created_at)=$m->year"))->whereRaw(DB::raw("MONTH(created_at)=$m->month"))
->orderBy('created_at','desc')
->get();
The second query returns all the rows of any month. I'm executing this query in a foreach loop for all of the months that are returned in the first query.
I am trying to combine this two query into one so that I can get a group of the results by months and years and also all the details of that month.
Any help, suggestions or idea would be extremely helpful.
[Note: For the date in second query, this date is created_at result from the first query.]
Thank you.
The way I read your question is as following: The second query is executed in a loop with results from the first one. Is that right? In my answer I have explained a way to execute the second query just one time instead of in a loop. You'd still have to execute the first query once.
So, I think that you are better of using the Php collection methods:
$results = Gk::where('user_id',$request->user_id)
->orderBy('created_at','desc')
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
});
The groupBy method has to return an attribute on which you want to group the elements. For this example I think that using a yyyy-mm format will do fine.
Reference: https://laravel.com/docs/5.5/collections#method-groupby
Edit: Maybe you can also get rid of the orderBy method call because you are grouping by afterwards:
$results = Gk::where('user_id',$request->user_id)
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
});
Edit 2: To combine the information of the two queries, you could do something like the following:
$results = Gk::where('user_id',$request->user_id)
->get()
->groupBy(function (Gk $item) {
return $item->created_at->format('Y-m');
})->map(function(Collection $rows) {
return [
'sum(ton)' => $rows->sum('ton'),
'total' => $rows->count(),
'sum(w)' => $rows->sum('w'),
'rows' => $rows
];
);
Note that I have omitted a few of the selected columns in your first query because they are not unique in the given group by. But feel free to add any logic in the map function. Because we use map() after groupBy, every call of map() will receive a collection of items for one month. You can that use that fabulous collection magic to calculate all values that you need and reduce the number of queries to just one.
I'm running this code on Laravel. I'm adding filters/ordering if I receive them and I'm altering the query before running it and then paginate the results.
$aDatas = DB::table('datas');
if (!empty($aLocations)) {
foreach ($aLocations as $oLocation) {
$aDatas->orWhere('pc', '=', $oLocation->pc);
}
}
if (!empty($oFilters->note)) {
$aDatas->where('note', '>=', $oFilters->note);
}
if (!empty($oFilters->nb_comments)) {
$aDatas->where('nb_comments', '>=', $oFilters->nb_comments);
}
if (!empty($oOrder->type)) {
$aDatas->orderBy($oOrder->type, $oOrder->sort);
}
// echo $aDatas->where('note', '>=', 5)->count() ????
It's working fine.
But I'd like to use these results to count several parts of it.
The last line shows what I tried to do, counting how many rows in these filtered results have a note >= 5. But doing this will actually filter my original data.
I thought about assigning $aDatas to another variable and then count on this, but I'll have many counts and that seems dirty.
Is there a sweet way to do this ?
Just save your datas an replace the last line with this:
$datas =$aDatas->where('note', '>=', 5)->get();
echo $datas->count();
//use datas here for more action.
For all of your requirement, you might want to resolve in making several queries because a single query will not be able to do that(based from what I know)
//this is to get your total of note greater than 5
$query = DB::table('datas');
$query->where('note', '>=', 5);
$data = $query->paginate(10);
$count = $data->getTotal();
to get your other data
If you are working with pagination, use getTotal() instead
$query = DB::table('datas');
$query->select(
DB::raw('COUNT(stars) AS count'),
DB::raw('starts'),
);
$query->where('notes', '>=', 5);
$query->groupBy('stars');
$data = $query->get();