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

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

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();

Laravel Eloquent condition to fetch hierarchy level

Laravel Eloquent condition to fetch hierarchy level.
I have a table named routes and it is self-referencing
Sample data:
(PK)
Id title route_id
1 users null
2 home null
3 foo 1
4 bar 3
5 hoge 3
I would want to have a function to get routes according to its hierarchy
$this->routes->getByHierarchyLevel(1);
// results
Id title route_id
1 users null
2 home null
$this->routes->getByHierarchyLevel(2);
// results
Id title route_id
3 foo 1
$this->routes->getByHierarchyLevel(3);
// results
Id title route_id
4 bar 3
5 hoge 3
Is there a single chained query builder/eloquent builder possible for this one?
I already made a custom function of this one but it is a looped query or the other solution is fetch all and filter.
I would suggest to introduce a new column level in your routes table and at the time of insertion detect their nested level and save it in your table, this way you can perform your filters easily without any extra overhead , otherwise you would need complex/expensive queries to be able to detect their level and apply filter
id
title
route_id
level
1
users
null
1
2
home
null
1
3
foo
1
2
4
bar
3
3
5
hoge
3
3

Construct Optimized Eloquent Query

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

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)
}

SQL Server 2014 Nested Blog comments sorting

I'm trying to build a small blog allowing people to add comments..
For comments I prepared a table like this:
ID PostID ParentID Date Title Text User ....
1 1 0
2 2 0
3 1 0
4 1 1
5 1 1
6 1 4
7 1 1
8 1 5
9 1 8
where if ParentID is not 0 means that this comment is not referred to the post but to the comment with that ID (is nested)
ie: assuming to select Post 1 will extract all comments except ID=2.
we have posts 1 and 2 on the root
posts 4,5,7 are nested in comment 1
post 6 is nested in 4 (triple nesting)
post 8 is nested in 5 (triple nesting)
post 9 is nested in 8 (quadruple nesting)
Therefore I expect the query returns the record in this order:
1
4
6
5
8
9
7
2
But I'm struggling with the query to achieve the above result.
Actually, for single nesting I find a solution, but for deeper nesting.. have really no idea..
I also thought that table schema used is not adequate..
On the other side I thought that such issue can be a common issue, but google didn't gave me any valuable result.. probably used wrong keywords..
Can you please suggest a path to solve this problem, or where to search for?
Thanks!
Jan
the solution is in Eric Weilinau's answer at this Post.
Basically it uses a recurring CTE
I modified a little to use ID value as Order and adding a further filter.
Here is the query:
WITH [NodeList] (
[Id], [ParentId], [Level], [Order]
) AS (
SELECT [Node].[Id]
, [Node].[ParentId]
, 0 AS [Level]
, Right('0000'+CONVERT([varchar](MAX), [Node].[ID]),4) AS [Order]
FROM [Node]
WHERE [Node].[ParentId] = 0
UNION ALL
SELECT [Node].[Id]
, [Node].[ParentId]
, [NodeList].[Level] + 1 AS [Level]
, [NodeList].[Order] + '|'
+ Right('0000' + CONVERT([varchar](MAX), [Node].[ID]),4) AS [Order]
FROM [Node]
INNER JOIN [NodeList] ON [NodeList].[Id] = [Node].[ParentId]
) SELECT [NodeList].[id],
[NodeList].[Level],
REPLICATE('-', [NodeList].[Level] * 4) + [Node].[Name] AS [Name]
FROM [Node]
INNER JOIN [NodeList] ON [NodeList].[Id] = [Node].[Id]
WHERE BlogID=1
ORDER BY [NodeList].[Order]
if somebody can find it helpful.

Resources