i have a query like this:
$players = PostBalance::where('post_id', $post->id)->orderBy('id','desc')->get();
It work well and return array with all values, Post balances have fields:
ID
score
post_id
user_id
I would like Delete user_id duplicated AND get the max score value. for example if i have:
[0] = 'id' => 1 , 'score'=> 10, 'user_id'=> 1, 'post_id' => 1
[1] = 'id' => 2 , 'score'=> 20, 'user_id'=> 1, 'post_id' => 1
[2] = 'id' => 3 , 'score'=> 30, 'user_id'=> 1, 'post_id' => 1
[3] = 'id' => 4 , 'score'=> 40, 'user_id'=> 2, 'post_id' => 1
[4] = 'id' => 5 , 'score'=> 50, 'user_id'=> 2, 'post_id' => 1
[5] = 'id' => 6 , 'score'=> 60, 'user_id'=> 2, 'post_id' => 1
I would like delete duplicates user_id and get only the user_id with max score:
RESULT:
[0] = 'id' => 3 , 'score'=> 30, 'user_id'=> 1, 'post_id' => 1
[1] = 'id' => 6 , 'score'=> 60, 'user_id'=> 2, 'post_id' => 1
You can use groupBy() and max() method like this (note: this will not actually delete the duplicates from DB, but work for your query):
$result = PostBalance::groupBy('user_id')
->max('score');
For further reference, see Laravel Docs
Or if you want to order the results by score, you can do it like this:
$result = PostBalance::orderBy('score', 'desc')
->groupBy('user_id')
->get();
Note: To get max of group by, try to first run orderBy(), then run groupBy() on the query instead.
Hope this helps!
Related
I get PDO rows array which contains the result:
parent_id , item_id
NULL 2
NULL 3
1 5
1 8
I want a new array where parent_id is not NULl
Means
new arr=[5,8]
You need to set new array from exits or to duplicate request with IS NULL condition. With array method, your code will show like this:
$arr = [
[
'parent_id' => null,
'item_id' => 2,
],
[
'parent_id' => null,
'item_id' => 4
],
[
'parent_id' => 2,
'item_id' => 20,
],
];
$new_arr = array_filter($arr,function ($item) {
return !$item['parent_id'];
});
print_r($new_arr);
** I have edited this to show how I got my code to work using array_search
I have an array, $arr1 with 5 columns as such:
key id name style age whim
0 14 bob big 33 no
1 72 jill big 22 yes
2 39 sue yes 111 yes
3 994 lucy small 23 no
4 15 sis med 24 no
5 16 maj med 87 yes
6 879 Ike larg 56 no
7 286 Jed big 23 yes
This array is in a cache, not a database.
I then have a second array with a list of id values -
$arr2 = array(0=>14, 1=>72, 2=>8790)
How do I filter $arr1 so it returns only the rows with the id values in $arr2?
I got my code to work as follows:
$arr1 = new CachedStuff(); // get cache
$resultingArray = []; // create an empty array to hold rows
$filter_function = function ($row) use ($arr2) {
return (array_search($row['id'], $arr2));
};
$resultingArrayIDs = $arr1->GetIds($filter_function, $resultingArray);
This gives me two outputs: $resultingArray & $resultingArrayIDs both of which represent the intersection of the $arr1 and $arr2.
This whole task can be accomplished with just one slick, native function call -- array_uintersect().
Because the two compared parameters in the custom callback may come either input array, try to access from the id column and if there isn't one declered, then fallback to the parameter's value.
Under the hood, this function performs sorting while evaluating as a means to improve execution time / processing speed. I expect this approach to outperform iterated calls of in_array() purely from a point of minimized function calls.
Code: (Demo)
var_export(
array_uintersect(
$arr1,
$arr2,
fn($a, $b) =>
($a['id'] ?? $a)
<=>
($b['id'] ?? $b)
)
);
Something like this should do it, provided I've understood your question and data structure correctly:
$dataArray = [
[ 'key' => 0, 'id' => 14 , 'name' => 'bob' , 'style' => 'big' , 'age' => 33 , 'whim' => 'no' ],
[ 'key' => 1, 'id' => 72 , 'name' => 'jill' , 'style' => 'big' , 'age' => 22 , 'whim' => 'yes' ],
[ 'key' => 2, 'id' => 39 , 'name' => 'sue' , 'style' => 'yes' , 'age' => 111 , 'whim' => 'yes' ],
[ 'key' => 3, 'id' => 994 , 'name' => 'lucy' , 'style' => 'small' , 'age' => 23 , 'whim' => 'no' ],
[ 'key' => 4, 'id' => 15 , 'name' => 'sis' , 'style' => 'med' , 'age' => 24 , 'whim' => 'no' ],
[ 'key' => 5, 'id' => 16 , 'name' => 'maj' , 'style' => 'med' , 'age' => 87 , 'whim' => 'yes' ],
[ 'key' => 6, 'id' => 879 , 'name' => 'Ike' , 'style' => 'larg' , 'age' => 56 , 'whim' => 'no' ],
[ 'key' => 7, 'id' => 286 , 'name' => 'Jed' , 'style' => 'big' , 'age' => 23 , 'whim' => 'yes' ]
];
$filterArray = [14, 72, 879];
$resultArray = array_filter( $dataArray, function( $row ) use ( $filterArray ) {
return in_array( $row[ 'id' ], $filterArray );
} );
View this example on eval.in
However, your question appears to suggest this data might be coming from a database; is that correct? If so, perhaps it's more efficient to pre-filter the results at the database-level. Either by adding a field in the SELECT query, that represents a boolean value whether a row matched your filter ids, or by simply not returning the other rows at all.
One way is with foreach loop with array_search()
$result = [];
foreach ($arr1 as $value) { // Loop thru $arr1
if (array_search($value['id'], $arr2) !== false) { // Check if id is in $arr2
$result[] = $value; // Push to result if true
}
}
// print result
print_r($result);
As #DecentDabbler mentioned - if the data is coming out of a database, using an IN on your WHERE will allow you to retrieve only the relevant data.
Another way to filter is to use array functions
array_column extracts the value of the id column into an array
array_intersect returns the elements which are in both $arr1['id'] and $arr2
array_flip flips the resulting array such that the indices into $arr1 indicate the elements in both $arr1 and $arr2
$arr1 = [ [ 'id' => 14, 'name' => 'bob'],
['id' => 72, 'name' => 'jill'],
['id' => 39, 'name' => 'sue'],
['id' => 994, 'name' => 'lucy'],
['id' => 879, 'name'=> 'large']];
$arr2 = [ 14,72,879 ];
$intersection = array_flip(array_intersect(array_column($arr1,'id'),$arr2));
foreach ($intersection as $i) {
var_dump($arr1[$i]);;
}
I am using bootstrap progress bar to display stats.
I want to know how many scored 10 points out of total no of rows.
$q="SELECT * FROM users";
$r = mysqli_query($con,$q);
$total = mysqli_num_rows($r);
Name email score time
Hello abc#gmail.com 10 15
Hello abc#gmail.com 58 10
Test def#gmail.com 10 12
Stack xyz#gmail.com 90 20
Test def#gmail.com 50 40
$q="SELECT COUNT(Name) FROM users WHERE score='10' ";
You can use this simple query to get it done :-
SELECT COUNT(name), score
FROM users
GROUP BY score
This would get the total for each individual score (10,9,8).
If you want total only for value 10. Use this instead.
SELECT COUNT(name), score
FROM users
WHERE score=10
This will loop through the $total array and assign all the values less than 10 into an array then loop through that array to print out how many out of total for each less than 10.
$total = [
0 => [
'name' => 'Hello',
'email' => 'abc#gmail.com',
'score' => 10,
'time' => 15
],
1 => [
'name' => 'Hello',
'email' => 'abc#gmail.com',
'score' => 58,
'time' => 10
],
2 => [
'name' => 'Test',
'email' => 'def#gmail.com',
'score' => 10,
'time' => 12
],
3 => [
'name' => 'Stack',
'email' => 'xyz#gmail.com',
'score' => 90,
'time' => 20
],
4 => [
'name' => 'Test',
'email' => 'def#gmail.com',
'score' => 50,
'time' => 40
],
];
$sizeOfArray = count($total);
$arrayOfScoresLessThanTen = [];
foreach($total as $value) {
if($value['score'] <= 10) {
if(isset($arrayOfScoresLessThanTen[$value['score']])) {
$arrayOfScoresLessThanTen[$value['score']] ++;
}
else {
$arrayOfScoresLessThanTen[$value['score']] = 1;
}
}
}
foreach($arrayOfScoresLessThanTen as $key => $scoresLessThanTen) {
echo 'Score: '. $key . ' number scored out of total: '. $scoresLessThanTen . '/'.$sizeOfArray;
}
This has been tested and works with the array $total that I created to match the one you had in your table. I added my $total array so that you can test it for yourself.
Good day!
I am running an update on two tables at once , but when I run the query cakephp is increasing the value of a column like a column with auto increment .
I have the following array:
$this->request->data = array(
'Model1' => array(
'id'=>'9',
'nome_fantasia' => 'Campos',
'razao_social' => 'Campos ',
'email' => 'testes#teste.com.br',
'responsavel_cpf' => '4456456465',
'ativo' => '1'
),
'Model2' => array(
(int) 0 => array(
'id' => '43',
'relacionamento_id' => '9',
'endereco' => 'Rua ******',
'numero' => '123',
'bairro' => 'bairro',
'cep' => '033888222'
)
)
);
And then the bass I have the update function:
$this->Modelo1->id = $this->request->data('Modelo1.id');
$this->Modelo1->saveAll( $this->request->data );
Ok , it does the Update in Model1 when it runs the update in Modelo2 it saves all the data but in the ' relacionamento_id ' instead of putting '9' as in this-> request- > data it is increasing with some ghost value. .. I realized that every time I run the query it will increase the number , for example
Attempt 1 = relacionamento_id = 50
Attempt 2 = relacionamento_id = 51
Attempt 3 = relacionamento_id = 52
Attempt 4 = relacionamento_id = 53
If I save both models separately it is right, but I would save direct .
I am working on a site where I have a table with "catches" (people have caught fish with a particular lure). The lure_used category is an integer.
I want to find the users "best lure". So i want to loop through all the user_catches rows and return an array that has each lure and how many times it was used.
So for example we might have
catch_1 | lure_used = 5,
catch_2 | lure_used = 3,
catch_3 | lure_used = 6,
catch_4 | lure_used = 3,
so from that i would like to know that 5 and 6 occur 1 time while 3 occurs twice. Therefore 3 is the most successful lure.
I know that I could probably use "MAX" in mysql queries, but i'm not really farmiliar with it and attempts have failed.
I have been able to create an array of lures used like:
$lures = array(5, 3, 6, 3);
So maybe i could just loop through that and output something like...
5 = 1, 3 = 2, 6 = 1.
I guess i'm grasping at straws haha, anyone have a better idea on how to get this done?
Here are all the fields in the "user_catches" table:
'id' => $row->id,
'user_id' => $row->user_id,
'species' => $row->species,
'season' => $row->season,
'lure_used' => $row->lure_used,
'depth' => $row->depth,
'exact_depth' => $row->exact_depth,
'presentation' => $row->presentation,
'catch_weight' => $row->catch_weight,
'length' => $row->length,
'fishing_from' => $row->fishing_from,
'moon_phase' => $row->moon_phase,
'water_temp' => $row->water_temp,
'water_quality' => $row->water_quality,
'notes' => $row->notes,
'rod' => $row->rod,
'reel' => $row->reel,
'line' => $row->line,
'rig' => $row->rig,
'catch_image' => $row->catch_image,
'weather' => $row->weather,
'temp' => $row->temp,
'humidity' => $row->humidity,
'wind' => $row->wind,
'pressure' => $row->pressure,
'visibility' => $row->visibility,
'location' => $row->location,
'weather_icon' => $row->weather_icon,
'catch_date' => $row->catch_date,
SELECT lure, count (*) as count
from user_catches
GROUP BY lures
ORDER BY count;