Laravel Eloquent GroupBy statement - laravel

I have this table and i'm trying to achieve a multiple groupBy and distinct through Laravel with a sum of duration. Basically, i need to find in table multiple ids passed from controller and then if windows, method and type are the same, sum the duration value.
Here is table structure
+-----+---------+--------+----------+------+
| ids | windows | method | duration | type |
+-----+---------+--------+----------+------+
| 1 | 2 | 3 | 5 | 2 |
+-----+---------+--------+----------+------+
| 2 | 2 | 3 | 5 | 2 |
+-----+---------+--------+----------+------+
| 3 | 2 | 3 | 5 | 2 |
+-----+---------+--------+----------+------+
and here is the statement that i try to use:
$tickets_g = \App\Models\Ticked::whereIn('id', $tickets)
->select('categoria', 'tipologia', 'priority', 'durata')
->distinct()
->GroupBy('categoria')
->GroupBy('tipologia')
->GroupBy('priority')
->sum('durata')
->get();
Can someone help me to figure out?

Fixed myself this is the correct query if someone stuck in the same issue:
$tickets_g = \App\Models\Ticked::select('support_ticked.*', DB::raw("SUM(support_ticked.durata) as durata_totale"))
->groupBy('support_ticked.tipologia','support_ticked.priority', 'support_ticked.categoria')
->get();

Related

Laravel - Eloquent filter where Left Join does not exist

I am trying to figure out how to make this query work. These two tables do not have a direct relation (i.e. hasOne, hasMany, etc). I am looking to only get back records from client_vendor_relationship that do NOT have a collection_opt_in. Since I don't have a way of doing ->whereDoesntHave(), I am not sure how to get this data back.
client_vendor_relationship
| id | client_id | vendor_id | active |
|----|-----------|-----------|--------|
| 1 | 23484 | 1872 | 1 |
| 2 | 5643 | 345 | 1 |
| 3 | 431 | 4443 | 1 |
collection_opt_in
| id | client_id | vendor_id | year |
|----|-----------|-----------|------|
| 1 | 23484 | 23484 | 2020 |
| 2 | 23484 | 23484 | 2019 |
| 3 | 431 | 4443 | 2019 |
Current Query
$relationships = ClietVendorRelationship::where('active', 1)
->leftJoin('collection_opt_in', function($join){
$join->on('client_vendor_relationship.client_id', '=', 'collection_opt_in.client_id')
->on('client_vendor_relationship.vendor_id', '=', 'collection_opt_in.vendor_id');
})
->where() // Not sure what to put here to ONLY get rows back that the left join didnt find entries for
->groupBy('client_vendor_relationship.id')
->get();
The end goal of this above query would to be to only get the row back from client_vendor_relationship with the id of 2. I need to do this in Eloquent. I know I could easily just do a collection filter but the front end table I am using requires an eloquent query to be returned.
why using left join? while there is another straightforward ways?
you can use 'whereNotExists':
$relationships = ClietVendorRelationship::where('active', 1)
->whereNotExists(function ( $query){
$query->select('collection_opt_in.id')->from('collection_opt_in')->
whereColumn('collection_opt_in.client_id', '=', 'client_vendor_relationship.client_id')->
whereColumn('collection_opt_in.vendor_id', '=', 'client_vendor_relationship.vendor_id');
})
->groupBy('client_vendor_relationship.id')
->get();
also i must say i don't recommend using group by without aggregation

Laravel - Get Data from Table where clause in other table

I have this following 2 tables:
Table: Products
+----+---------+-------------+
| id | fn_id | created_at |
+----+---------+-------------+
| 1 | 4 | SOME TIME |
| 2 | 5 | SOME TIME |
| 3 | 6 | SOME TIME |
| 4 | 10 | SOME TIME |
| 5 | 10 | SOME TIME |
+----+---------+-------------+
Table Fn
+----+---------+-------------+
| id | fn_id | created_at |
+----+---------+-------------+
| 1 | 10 | SOME TIME |
| 2 | 11 | SOME TIME |
| 3 | 12 | SOME TIME |
| 4 | 14 | SOME TIME |
+----+---------+-------------+
And a User Input which is giving me a timestamp ($user_timestamp).
Now I need to get all produtcs, where
products.fn_id is 10
fn.fn_id is 10
fn.created == $user_timestamp
The products model has this relation:
public function fn() {
return $this->hasMany('App\FN', 'fn_id', 'fn_id');
}
Now I've tried multiple things like a where query where I want to check if the fn_id on both are "10" and the created_at value of the fn table is equal to $user_timestamp.
However, I wasn't able to do it.
$products = Products::with('fn')->where('fn.fn_id', function ($query) use ($user_timestamp) {
$query->where([['fn_id', 10],['created_at', $user_timestamp]]);
})->get();
You would have to use whereHas to constrain Products based on fn.
$products = Products::with('fn')->whereHas('fn', function($q) use($user_timestamp){
$q->where('fn_id', 10)->where('created_at', $user_timestamp);
})->get();
try this
$id_to_search=10;
$products = Products::with('fn')->where('fbn_id',$id_to_search)->whereHas('fn', function($q) use($user_timestamp,$id_to_search){
$q->where('fn_id', $id_to_search)->where('created_at', $user_timestamp);
})->get();

How to make Eloquent query for Group by, with HAVING and MAX

I have SQL query which I need to convert to Eloquent and no idea where to write MAX conditions. How it is posible to convert it without much Raw sql? Thank you!
SELECT bike_id
FROM bike_filters
GROUP BY bike_id
HAVING
MAX(bike_category_id in (416,11111)) = 1
AND MAX(bike_category_id in (5555,779)) = 1
AND MAX(bike_category_id in (5555,772)) = 1
Table Structure:
| id | bike_id | bike_category_id |
| 1 | 3 | 416 |
| 2 | 3 | 779 |
| 3 | 3 | 344 |
| 4 | 3 | 332 |
| 5 | 4 | 444 |
| 5 | 5 | 555 |
The purpose of this query is to get bike_ids, which has all parameters by the query - bike can have 20 filters, but if user searches by 5 and bike matches them, we get bike_id by this query.
For this you could use havingRaw() which would look something like:
$query = DB::table('bike_filters')
->select('bike_id')
->groupBy('bike_id')
->havingRaw('MAX(bike_category_id in (416,11111)) = 1')
->havingRaw('MAX(bike_category_id in (5555,779)) = 1')
->havingRaw('MAX(bike_category_id in (5555,772)) = 1')
->get();

Laravel: Query the models where the relationship is greater than 0

I'm doing a Laravel query to query a list of elements that his relationship is grater than 0.
The table concerts:
| ID | NAME |
|----|-----------|
| 1 | Concert A |
| 2 | Concert B |
| 3 | Concert C |
And the Position table.
| ID | concert_id | user_id | Content |
|----|----------------|------------|----------|
| 1 | 1 | 1 | xxx |
| 2 | 1 | 2 | yyy |
| 3 | 3 | 1 | zzz |
| 4 | 3 | 2 | www |
| 5 | 1 | 3 | xyx |
| 6 | 3 | 3 | rer |
The query that I need to do is, get the concerts where their position has in the content a value like $some_query$.
The code I've is the following:
$result = $this->model->whereHas('positions')
->with(['positions' => function ($query) {
$query->where('content', 'like', "%{$content}%");
}])->get();
But as far as I can tell, this will bring all the concerts, and also this is going to bring only the positions that has the desired content.
So I've two problems, the first one is I need to get the concerts that his queried positions are greather than 0.
And the second one is that also I need to bring all the positions, not only the queried ones.
Basically the query is just a way to know which concerts I need to bring.
Is there possible to achieve this on a single query?
You'll have to move your query to the whereHas.
If I understood well, this is what you want:
$result = $this->model
// Take the Concerts that has positions with a similar content
->whereHas('positions', function ($query) use ($content) {
$query->where('content', 'like', "%{$content}%");
})
// Take (all) the Positions of these concerts
->with('positions')
->get();

Sum of the grouped distinct values

This is a bit hard to explain in words ... I'm trying to calculate a sum of grouped distinct values in a matrix. Let's say I have the following data returned by a SQL query:
------------------------------------------------
| Group | ParentID | ChildID | ParentProdCount |
| A | 1 | 1 | 2 |
| A | 1 | 2 | 2 |
| A | 1 | 3 | 2 |
| A | 1 | 4 | 2 |
| A | 2 | 5 | 3 |
| A | 2 | 6 | 3 |
| A | 2 | 7 | 3 |
| A | 2 | 8 | 3 |
| B | 3 | 9 | 1 |
| B | 3 | 10 | 1 |
| B | 3 | 11 | 1 |
------------------------------------------------
There's some other data in the query, but it's irrelevant. ParentProdCount is specific to the ParentID.
Now, I have a matrix in the MS Report Designer in which I'm trying to calculate a sum for ParentProdCount (grouped by "Group"). If I just add the expression
=Sum(Fields!ParentProdCount.Value)
I get a result 20 for Group A and 3 for Group B, which is incorrect. The correct values should be 5 for group A and 1 for group B. This wouldn't happen if there wasn't ChildID involved, but I have to use some other child-specific data in the same matrix.
I tried to nest FIRST() and SUM() aggregate functions but apparently it's not possible to have nested aggregation functions, even when they have scopes defined.
I'm pretty sure there is some way to calculate the grouped distinct sum without needing to create another SQL query. Anyone got an idea how to do that?
Ok I got this sorted out by adding a ROW_NUMBER() function my SQL query:
SELECT Group, ParentID, ROW_NUMBER() OVER (PARTITION BY ParentID ORDER BY ChildID ASC) AS Position, ChildID, ParentProdCount FROM Table
and then I replaced the SSRS SUM function with
=SUM(IIF(Position = 1, ParentProdCount.Value, 0))
Put a grouping over the ParentID and use a summation over that group,
eg:
if group over ParentID = "ParentIDGroup"
then
column sum of ParentPrdCount = SUM(Fields!ParentProdCount.Value,"ParentIDGroup")

Resources