Remove duplicates from groupBy - laravel

I would like to find out how many Users have Swipes per day without duplicates of user_id within group.
So if a User has swiped multiple times on a day, I want the User only show once per group (per day). I am not really interested in the actual Swipes but rather in the swipe count per day.
I tried:
Swipe::all()->groupBy(function($item){ return $item->created_at->format('d-M-y'); })->unique('user_id')

To remove duplicate data, you can use unique().
I create an example for you.
I have dummy data like
.
So you want the result is data grouped by created_at and on every date return how many users swipe it but without duplicate user?
The code should be like:
$collect = Swipe::all()->groupBy(function($data){
return $item->created_at->format('d-M-y');
})->transform(function($dataGrouped,$date){
return [
$date => $dataGrouped->unique('user_id')
];
});
The result will be like:

Related

Laravel 8 - count clicks but user can't spam the function

In my website I track clicks on a specific link and save the count on database with this function:
public function redirect($url)
{
$data = Class::where('url', $url)->first('clicks');
$cnt = $data->clicks;
$cnt++;
$sql = Class::where('url', $url)->update([
'clicks' => $cnt,
]);
if (!$sql) {
abort(500);
}
return redirect('https://website.com/'.$url);
}
the problem is if someone spam the link , the count goes up. I want stop count if user clicked on link 5mins ago.
he will redirected to the link but count doesn't go up.
I'm new so it's so good if you explain it with details. Thanks
I would create a new table, lets call it link_clicks. You will need 3 columns, one to identify the person, one to get the time and one to identify the link (I dont exactly know how you store the links you want to observe).
So more or less you will have the following table:
link_clicks
user_id
link_id
created_at
If the users are always logged in, I would store the user_id, if they are not logged in, I would store the IP-address. So instead of user_id make a column called ip or ip-address.
Afterwards you can easily get the last click and its time.
--Example
Your new table contains following entry:
user_id = 1, link_id = 1 and created_at = 2021-04-21 19:00:00
Now in your controller you get the current date_time date("Y-m-d H:i:s") and the user id like that: auth()->id(). You can also define your time treshold in minutes e.g max_dif = 5.
Afterwards you can query the table for all clicks for the user. You can either make the time comparision in your where() statement or you can make some comaprison in your php code to check if the time treshhold is reached.

Laravel get row with records above and below it

I have a Laravel 4.2 project where I get data from a SQL DB and I can display onto the page. I can select the single record just fine, but I want to also show the records around the one selected.
For example, I want to show the 5 records above and below the one selected. Im not sure how to do this in Laravel.
$gradschoolrange = MOGRadschool::where('Title', '=', $gradschool)->get();
In the above example $gradschool might be "Test College", it will return that with a value, but I want to show all the other related records around it with those values too. The results should look something like this:
ABC College
Another College
Blah College
Go To College
Test College
Yet Another College
Yo Yo College
College College
Something College
Eating College
As there's no ordering specified in your initial query, I'm assuming you want 5 next/previous records according to primary key (id? - if not, you would obviously need to change that) in the table?
Given that IDs may not be numerically sequential, we can't simply assume that the previous 5 rows will be the ID of the row with title = $gradschool minus 5, so wondered if this might work:
$initial = MOGRadschool::where('Title', $gradschool)->first(); // get the initial row with the title of $gradschool
$result = MOGRadschool::where('id', '<', $initial->id)->take(5)->orderBy('id', 'DESC') // new query getting the previous 5 rows, by ID
->union(MOGRadschool::where('id', '>', $initial->id)->take(5)) // union a second query getting the next 5 rows by ID
->get() // get the result as a collection
->add($initial) // add the initial row to the collection
->sort(); // sort the collection (by id) so that the initial row is in the middle
So the output is a collection containing the initial row in the middle, with up to 5 records either side. You also have the initial row to highlight the output, if you need that.
If you want it based on the IDs, which is what I understand from your issue, something like this should work:
$selectedGradSchool = MOGRadschool::where('Title', '=', $gradschool)->get()->first();
$aboveSelected = MOGRadschool::where('id', '<=', $selectedGradSchool->id)
->orderBy('id', 'desc')
->take('5')
->get();
$belowSelected = MOGRadschool::where('id', '>' $selectedgradSchool->id)
->take('5')
->get();
//Concatenate both results
$schoolRange = $aboveSelected->concat($belowSelected);
Now the collection should look similar to your desired result.

Laravel 5.4 - group by, count and join

I have two tables (models have the same name as the tables):
StatusNames: id|name
and
CurrentUserStatus: id|user_id|status_id
At the moment CurrentUserStatus is empty, and StatusNames have several records inserted (Active, Inactive, On Pause, Terminated...).
I need to get all data from CurrentUserStatus and show how much are there within each status (given the current tables, next to each status name there should be zero (0)).
Is this possible to do with one query?
So whatever I assumed you can do something like this:
$dataset = CurrentUserStatus::whereHas('status')
->with('status')
->withCount('status')
->orderBy('status_count', 'dsc')
->get();
Hope this helps.

Get first record of each entity order by a column

I have a query in linq that fetch students assessments data something like
new {x.StudentId, x.StudentAssessmentId, x.AssessmentName, x.SubmittedDate}
then I perform some operations on this list to get only last added student assessment per student, I get last studentassessment by finding the max id of studentassessment,
so I finally get last studentassessments data of all the students.
Is there a way to do this directly in the initial list?
I thought about the way to group the results by student Id and select max of studentassessmentid, like
group x.StudentAssessmentId by x.StudentId
select new {x.Key, x.Max()}
in this way I will get student with there last studentassessmentid which is what I want but this will only give me studentassessment ids while I want other data also like AssessmentName, SubmittedDate etc.
Try something like this:
group x.StudentAssessmentId
by new {
x.StudentId,
x.AssessmentName,
x.SubmittedDate }
into g
select new
{
g.Key.StudentId,
g.Key.AssessmentName,
g.Key.SubmittedDate,
g.Max(),
}

How can this query be improved?

I am using LINQ to write a query - one query shows all active customers , and another shows all active as well as inactive customers.
if(showall)
{
var prod = Dataclass.Customers.Where(multiple factors ) (all inactive + active)
}
else
{
var prod = Dataclass.Customers.Where(multiple factors & active=true) (only active)
}
Can I do this using only one query? The issue is that, multiple factors are repeated in both the queries
thanks
var customers = Dataclass.Customers.Where(multiple factors);
var activeCust = customers.Where(x => x.active);
I really don't understand the question either. I wouldn't want to make this a one-liner because it would make the code unreadable
I'm assuming you are trying to minimze the number of roundtrips?
If "multiple factors" is the same, you can just filter for active users after your first query:
var onlyActive = prod.Where(p => p.active == true);
Wouldn't you just use your first query to return all customers?? If not you'd be returning the active users twice.
Options I'd consider
Bring all customers once, order by 'status' column so you can easily split them into two sets
Focus on minimizing DB roundtrips. Whatever you do in the front end costs an order of magnitude less than going to the DB.
Revise user requirements. For ex. consider paging on results - it's unlikely that end user will need all customers at once.

Resources