Construct Optimized Eloquent Query - laravel

I have this table:
Permits Table
id parent_id user_id renewed_at
1 0 1 2019-01-01
2 0 8 2019-01-01
3 1 7 2019-01-02
4 1 2 2019-01-03
5 2 3 2019-01-02
6 0 2 2019-01-02
7 6 9 2019-01-03
8 2 2 2019-01-09
9 0 3 2019-01-10
10 9 2 2019-01-11
11 9 5 2019-01-12
The permits undergoes on renewal indicated on the parent_id column.
The thing is the permit can be renewed by different persons indicated on user_id field. A user can be considered as the owner of the permit if he is the latest one who made the renewal.
How to construct an optimized eloquent query that will get all permit that was owned by a specific person, for example = user with id number 2
What I did is:
Get all latest record
Filter the result from step 1 if user_id=2
The problem here is that this table has 100K rows making my query very expensive.
UPDATE 1:
$records_raw = Permits::groupBy('parent_id')
->where('parent_id', '>', 0)
->get([DB::raw('MAX(id) as id')])
->pluck('id');
$my_permits = Permits::where('user_id', Auth::id())
->whereIn('id', $records_raw)
->get();

You can use laravel Eloquent
for example you want the last record of user 2 (user_id=2)
$user_id = 2;
Permits::where('user_id',$user_id)->orderBy('renewed_at','desc')->first();
it takes the latest record added for user_id=2.....means record 8
8 2 2 2019-01-09
this is optimize query and not expensive
Update:
$user_id = 2;
Permits::where('user_id',$user_id)->where('parent_id','!=',0)->orderBy('renewed_at','desc')->get();
This will return what you want
hope this is helpfull

Do not use a query cache and recommend to profile your queries Using
DebbugBar ->https://github.com/barryvdh/laravel-debugbar
Thanks and i hope to be a helpful comment

Related

Laravel sum/count nested relation

i have a problem with simple relations.
Tables looks like that:
table players
id user_id game_id
1 2 1
2 5 1
3 3 1
4 4 2
5 2 2
table games
id result (win or lose)
1 1
2 0
What i need in result is:
Players Wins Losses
John 3 2
Philip 2 2
Jack 1 3
I tried alot of queries but i cant get proper result.
This one
`"select * from `players` inner join `games` on `players`.`game_id` = `games`.`id`"`
This one is best i can do, but its raw and no idea how to rewrite it to DB:: or Eloquent. And its not grouping anyway.
you can directly count from relation with model.
$category = Category::find($id);
$category->children->count();

How to limit the record of children's attribute in laravel eloquent

I am creating a comment section using laravel with the example entries below:
id | comment | parent_id
1 test 1
2 test 1
3 test 1
4 test 2
5 te 2
6 test 1
7 test 2
I get these data from an API request. Let's say, I want to get all comments and limit the replies up to 2 records per query. From the given test sample above, the result should be:
id | parent_id
1 1
2 1
4 2
5 2
My question is, how to get all replies (parent_id > 0) and limit & offset the query per request?
My current query is:
Comment::where('parent_id', '>' , 0)->get();
I think you should use pagination to limit the number of the elements:
Comment::where('parent_id', '>' , 0)->paginate(15);
Replace the "15" with your limit.
Also, you can check Laravel docs about pagination: https://laravel.com/docs/7.x/pagination

Distinct on two columns with same data type

In my game application I have a combats table:
id player_one_id player_two_id
---- --------------- ---------------
1 1 2
2 1 3
3 3 4
4 4 1
Now I need to know hoy many unique users played the game. How can I apply distinct, count on both columns player_one_id and player_two_id?
Many thanks.
By using union you can get unique distinct value.
$playerone = DB::table("combats")
->select("combats.player_one_id");
$playertwo = DB::table("combats")
->select("combats.player_two_id")
->union($playerone)
->count();

How to get product list related to other sale transaction count in Laravel?

I'm a newbie in Laravel and working on a small e-commerce project. I need to get products list that related to transaction count in the transaction table. Below is my demo data.
tb_product:
product_id product_name
1 A
2 B
3 C
tb_transaction:
transaction_id product_id
1 2
2 1
3 2
4 2
5 1
6 3
From tb_transaction. I have sale list as below
B = 3sales, A =2sales, C=1sale
I need to generate Laravel eloquent result like [{B...},{A...},{C...}] (count from max to min). I had tried some from google but no luck. Appreciated for advice, Thanks.
Try the below query,
DB::table('tb_product')
->select('tb_product.product_id', 'tb_product.product_name', DB::raw("count('tb_transaction.product_id') as salesCount"))
->join('tb_transaction', 'tb_transaction.product_id', 'tb_product.product_id')
->orderBy('salesCount', 'DESC')
->groupBy('tb_product.product_id', 'tb_product.product_name')
->get()

Select and sum multiple columns for statistic purposes with Laravel query

I have one table scores where I have saving users scores. It's looks like this
table `scores`
id | points | user_id
1 5 1
2 2 1
3 4 1
4 1 3
5 10 2
I want to select each user, sum his points and show as a ranking. The result from above should be
user_id | points
1 11
2 10
3 1
The query with which I came up is
$sumPoints = Scores::select( \DB::raw("sum(points) as numberOfPoints"), \DB::raw("count(id) as numberId"))->groupBy("user_id")->first();
The problem is in ->first() because it's return only one result.. it is working as must. If I try to use ->get() instead I've got Undefined property error. How should I use this?
The query which is working in phpmyadmin
SELECT count(id) as numberId, sum(points) as numberOfPoints FROM `points` GROUP BY `user_id`
You can use something like this
$sumPoints = Scores::select( \DB::raw("sum(points) as numberOfPoints"), \DB::raw("count(id) as numberId"))->groupBy("user_id")->get();
foreach($sumPoints as $point){
dd($point); //OR dd($point->numberOfPoints)
}

Resources