PHP - Sum array by defined condition of value - php

Please I need help to summarize a values of array by some conditions
i have this result query :
I want to calcul the Sum of calls for each user, i try with like this, but its show me the sum of all query [Users]
$array_out_ = array();
$usercalls = $usertalk = $userpause = $userwait = $userdispo = $userdead = 0;
foreach ($queryusers2 as $user) {
$current_user = $user['user'];
$usercalls += $user['calls'];
$usertalk += $user['talk'];
$userpause += $user['pause'];
$userwait += $user['wait'];
$userdispo += $user['dispo'];
$userdead += $user['dead'];
$array_out_[$current_user]['calls'] = $usercalls;
$array_out_[$current_user]['talk'] = $usertalk;
$array_out_[$current_user]['pause'] = $userpause;
$array_out_[$current_user]['wait'] = $userwait;
$array_out_[$current_user]['dispo'] = $userdispo;
$array_out_[$current_user]['dead'] = $userdead;
}
This method return me $usercalls (305 for agent29 ) and (436 for agent117)
But i want 305 ofr agent 29 and only 131 for the agent117
Thanks

I recommend you change the query SQL to something like this, where you can group and sum your data.
SELECT
tn.user,
SUM(tn.calls) AS usercalls,
SUM(tn.talk) AS usertalk,
SUM(tn.pause) AS userpause,
SUM(tn.wait) AS userwait,
SUM(tn.dispo) AS userdispo,
SUM(tn.dead) AS userdead
FROM tablename tn
GROUP BY tn.user
And this will return what you need:
agent29, 305, ...
agent117, 436, ...

Your values $usercalls,$usertalk,... are not re-initialized. and are cumulated for all users. Your code works only for the first user and only because your list is ordered by users.
You could initialize an array and sum directly inside it:
$array_out_ = array();
foreach ($queryusers2 as $user)
{
$current_user = $user['user'];
if (!isset($array_out_[$current_user])) {
$array_out_[$current_user] = [
'calls' => 0, 'talk' => 0, 'pause' => 0, 'wait' => 0,
'dispo' => 0, 'dead' => 0
];
}
$array_out_[$current_user]['calls'] += $user['calls'];
$array_out_[$current_user]['talk'] += $user['talk'];
$array_out_[$current_user]['pause'] += $user['pause'];
$array_out_[$current_user]['wait'] += $user['wait'];
$array_out_[$current_user]['dispo'] += $user['dispo'];
$array_out_[$current_user]['dead'] += $user['dead'];
}
See also the answer of Enric Borrallo Rodriguez

Related

php loop adds extra data to database

I have loop to store my data and it multiple the rows.
example
I have 3 rows with value of test1 and I need to add this rows to become 5
so I have 3 rows already
I add number in input field 2
I loop this 2 number and create new rows
previously 3 rows + 2 new rows = 5 rows in total
but currently I am getting 9 rows.
Code
foreach($request->input('barcodes') as $bb)
{
for ($i = 0; $i < $request->input('nonuiqueAmount'); ++$i) {
$barcode = new Barcode;
$barcode->product_id = $product->id;
$barcode->returned = false;
$barcode->serial_number = $bb['serial_number'];
$barcode->save();
}
}
In case you need a full code with logic here I shared it for you.
Any idea why I get more than my desire rows?
Solved
Thanks to u_mulder suggestion here is how I solved my issue
foreach($request->input('barcodes') as $bb)
{
$bbb = $bb['serial_number']; // added to get single serial number
}
for ($i = 0; $i < $request->input('nonuiqueAmount'); ++$i) {
$barcode = new Barcode;
$barcode->product_id = $product->id;
$barcode->returned = false;
$barcode->serial_number = $bbb; // changed
if($barcode->save()) {
$user = Auth::user();
$outlets = $user->outlets;
foreach($outlets as $outlet) {
DB::table('outlet_products')->insert([
'outlet_id' => $outlet->id,
'barcode_id' => $barcode->id,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
}

How generate column using for loop

How to make this function produce column occLvl_ loop 3 time and using explode to fetch each value from sql CONCAT. So the result will become like this.
[{
"accommodationID": "LA56",
"occLvl_0": "40.00",
"occLvl_1": "70.00",
"occLvl_2": "90.00"
}]
function getOccLevel(){
global $ehorsObj;
$occArray = array();
$sql = "SELECT accommodationID, GROUP_CONCAT(occLevelDesc) AS occLevels
FROM tblSamAccOccLevels
WHERE ACTIVE = 'y'
GROUP BY accommodationID
ORDER BY accommodationID ASC, occLevelDesc ASC ";
$GetResult = $ehorsObj->FetchData($sql, $ehorsObj->DEFAULT_PDO_CONNECTIONS);
while ($row = $GetResult->fetch()){
$occArray[] = array(
'accommodationID' => $row['accommodationID'],
);
//seem the method below is not working
for ($j = 0; $j < 3; $j++) {
$occArray["occLvl_".$j] = explode(",", $row['occLevels'])
}
}
header("Content-type: application/json");
$result = json_encode($occArray);
echo $result;
}
Result of the query
accommodationID occLevels
LA56 40.00, 70.00, 90.00
Making numerically named object properties/variables (occLvl_0 etc.) is generally a bad idea as it makes it difficult to work with them in any regular manner (e.g. using a loop). It is better practice to put the values into an array:
while ($row = $GetResult->fetch()){
$occArray[] = array(
'accommodationID' => $row['accommodationID'],
'occLvl' => explode(",", $row['occLevels'])
);
}
This will give you an output JSON that looks something like:
[
{
"accommodationID": "LA56",
"occLvl": [
40,
70,
90
]
},
{
"accommodationID": "PQ45",
"occLvl": [
30,
60,
100
]
},
...
]
And in your JS you can then iterate over the occLvl array to get the values.
If you need the data in the form you describe, then you need to iterate over the exploded occLevels value to generate the individual values, pushing them with the accommodationID into a new array and then pushing that array to $occArray:
while ($row = $GetResult->fetch()){
$this_occ = array(
'accommodationID' => $row['accommodationID'],
);
foreach (explode(",", $row['occLevels']) as $key => $occLvl) {
$this_occ["occLvl_$key"] = $occLvl;
}
$occArray[] = $this_occ;
}
Explode returns an array. You should explode before the loop and iterate through the result of that explode in the loop

How to add an int value to 'i' for each person in a multi-dimensional array every time they satisfy an if statement

I'm trying to create a weighted average based on how well each individual (who has their own array for 'name', 'gender', 'age' 'subject', etc) matches the criteria for the client.
eg.
If they study the right subject, i +100
else if they study a similar subject, i +75
else i * 1.
But I'm aiming for i to be updated for each candidate simultaneously. Feel free to tell me if I'm looking at this the wrong way or there is an easier way of doing this, more than happy to admit mistakes.
I wrote a bit of pseudo code for a simpler version, but I'm concerned that it doesn't fit the specification and would be a bit slow. Code below edited as suggested.
<?php
$sql = "SELECT * FROM data";
$result = mysqli_query($conn, $sql);
$candidates = array();
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
$candidates[] = $row;
}
}
//Not sure if this next bit makes sense or doing it wrong.
foreach($candidates as $i => $value) {
if (in_array($cand_subject, $searched_subject)) {
$i = $i + 1000;
}
elseif (in_array($cand_subject, $similar_subject)) {
$i = $i + 800;
} else {
$i = $i * 1;
}
You actually want something like this (explained everything in comments)
<?php
$pages_array = array( // intiate an array
array( // another array inside an array to define array of objects.
'name' => 'James',
'skills' => array("ai","php") //another array for array of strings
),
array( // same here
'name' => 'ben',
'skills' => array('C#', 'react', 'flutter')
)
);
foreach ($pages_array as $key => $value) { // for each of the array's
$score = 0;
if (in_array("ai", $value["skills"])) { // note $value["skills"] is an array. So we check if the array has the string "ai"
$score = 100;
}else{
$score = 75;
}
$value["score"] = $score; // add a field score into the array and put the value.
}
?>
This is same as you mentioned the puesdo code in your question.

Summing the values of two arrays in php

There is a problem:
After submitting a form I receive the indexed array as a SQL-query result and the goal is to sum each next array values with the values of previously received arrays and put the sums into result array
Example:
// 1st query result
$product_amount = [0 => 0.36,
1 => 0.14,
2 => 0.42]
// 2nd query result
$product_amount = [0 => 0.28,
1 => 0.12,
2 => 0.40]
// n-th query result
$product_amount = [0 => 0.16,
1 => 0.14,
2 => 0.42]
// the sum
$total = [0 => 0.80,
1 => 0.40,
2 => 1.24]
How to do it?
The code that creates an array:
function doseCount($num){
return ($num/100) * intval($_POST['portion']); //getting multiplier for productAmount() function
}
function productAmount(){
global $link; //connection to the MySQL server
if(isset($_POST['product'])){
$product_amount_query = 'SELECT va.vitamin_a, va.vitamin_b1, va.vitamin_b2, va.vitamin_b3, va.vitamin_b5,
va.vitamin_b6, va.vitamin_bc_b9, va.vitamin_b12, va.vitamin_c, va.vitamin_d, va.vitamin_e, va.biotin, va.vitamin_k,
va.flavonoids, va.lipoic_acid FROM products_list p, vitamins_amount va WHERE p.id = va.product_id AND p.name = ?';
$product_amount_stmt = mysqli_prepare($link, $product_amount_query);
mysqli_stmt_bind_param($product_amount_stmt, "s", $_POST['product']);
mysqli_stmt_execute($product_amount_stmt);
$result = mysqli_stmt_get_result($product_amount_stmt);
$product = mysqli_fetch_array($result, MYSQLI_NUM);
return $product_final_result = array_map('doseCount', $product);
mysqli_stmt_close($product_amount_stmt);
mysqli_close($link);
}
}
$product_amount = productAmount();
After submit $product_amount array gets new data and this new value must be summed with previous.
You could accomplish this by combining array_map and array_sum. If you're using PHP 5.6 or greater, which you should, you could write something like this:
$total = array_map(function (...$vals) {
return array_sum($vals);
}, ...$results);
Assuming that $results contains all of your $product_amount arrays.
If you want to build $total incrementally instead of passing all query results at once, you can do this:
// Initialize $total array
$total = [0, 0, 0];
// Update $total for each query
$total = array_map(function (...$vals) {
return array_sum($vals);
}, $total, $product_amount);
This problem can be solved with proper use of sessions:
if (empty($_SESSION['product_amount'])){
$_SESSION['product_amount'] = $product_amount;
}else{
foreach ($_SESSION['product_amount'] as $key => $value) {
$_SESSION['product_amount'][$key] += $product_amount[$key];
}
}
Special thanks to Mawia HL for his help.

PHP Array select result from other array

I have a sql table with some category, i get them in a array.. all fine but when i try to get data from another table foreach category, always return me for first category selected.
This is my code:
$gameguidecategoryes = array();
$gameguides = array();
$dbselectgameguidecategoryes = new DB_MSSQL;
$dbselectgameguidecategoryes->Database=$newweb_db;
$dbselectgameguidecategoryes->query("Select GameGuideCatNr,GameGuideCatName_$languageid as GameGuideCatName,GameGuideCatImage from GameGuide_Category where GameGuideCatVisible = 1 order by GameGuideCatOrder asc");
for($i=0;$i < $dbselectgameguidecategoryes->num_rows();++$i) {
if ($dbselectgameguidecategoryes->next_record()){
$GameGuideCatNr = $dbselectgameguidecategoryes->f('GameGuideCatNr');
$GameGuideCatName = $dbselectgameguidecategoryes->f('GameGuideCatName');
$GameGuideCatImage = $dbselectgameguidecategoryes->f('GameGuideCatImage');
}
$gameguidecategoryes_temp = array(
'ggcname' => $GameGuideCatName,
'ggcimg' => $GameGuideCatImage,
);
$gameguidecategoryes[$i] = $gameguidecategoryes_temp;
$dbselectgameguide = new DB_MSSQL;
$dbselectgameguide->Database=$newweb_db;
$dbselectgameguide->query("Select GameGuideID,GameGuideName_$languageid as GameGuideName from GameGuide_Content where GameGuideCat = $GameGuideCatNr and GameGuideVisible = 1 order by GameGuideOrder asc");
for($ii=0;$ii < $dbselectgameguide->num_rows();++$ii) {
if ($dbselectgameguide->next_record()){
$GameGuideID = $dbselectgameguide->f('GameGuideID');
$GameGuideName = $dbselectgameguide->f('GameGuideName');
}
$gameguides_temp = array(
'ggid' => $GameGuideID,
'ggn' => $GameGuideName,
);
$gameguides[$ii] = $gameguides_temp;
}
}
Why $gameguides return data only from first category?
Thank you
Your second loop keeps getting trashed by the first loop. e.g. Consider what happens:
You fetch your categories, and (let's pretend) there's 4 of them.
You store some information in $gameguidecategoryes[0]
You run the second query, get some content for category #0, say, 3 records
That gets stored in $gameguides[0], [1], [2]
Your outer loop ticks again, and you start on categoryes[1]
The inner loop ticks again, you get 4 records, and now you're storing them into the SAME again: $gameguides[0], [1], [2], [3], etc...
You've now trashed the data you fetched in the first loop, and will
do so for every category you fetch.
This code is very inefficient. You should learn how to use JOINs, and fetch into a single structure, e.g.
SELECT category.id, category.name, ...., content.id, content.name
FROM categories
LEFT JOIN content ON categories.id = content.category_id
ORDER BY ...
and then something like
$data = array();
while($row = fetch row from db) {
if (!isset($data[$row['category.id']]) {
$data[$row['category.id']] = array(
'name' => $row['category.name'],
'content' => array()
);
}
$data[$row['category.id']]['content'][] = array(
... save content data here
);
};
Better work on clean code
$gameguidecategoryes = $gameguides = $gameguidescategoryids = array();
$dbselectgameguidecategoryes = new DB_MSSQL;
$dbselectgameguidecategoryes->Database=$newweb_db;
$dbselectgameguidecategoryes->query("Select GameGuideCatNr,GameGuideCatName_$languageid as GameGuideCatName,GameGuideCatImage from GameGuide_Category where GameGuideCatVisible = 1 order by GameGuideCatOrder asc");
while ($dbselectgameguidecategoryes->next_record()) {
$gameguidescategoryids[] = $dbselectgameguidecategoryes->f('GameGuideCatNr');
$gameguidecategoryes[] = array(
'ggcname' => $dbselectgameguidecategoryes->f('GameGuideCatName'),
'ggcimg' => $dbselectgameguidecategoryes->f('GameGuideCatImage'),
);
}
if (count($gameguidescategoryids)) {
$dbselectgameguide = new DB_MSSQL;
$dbselectgameguide->Database=$newweb_db;
$dbselectgameguide->query("Select GameGuideID,GameGuideName_$languageid as GameGuideName from GameGuide_Content where GameGuideCat IN (".implode(',', $gameguidescategoryids).") and GameGuideVisible = 1 order by GameGuideOrder asc");
while ($dbselectgameguide->next_record()){
$gameguides[] = array(
'ggid' => $dbselectgameguide->f('GameGuideID'),
'ggn' => $dbselectgameguide->f('GameGuideName'),
);
}
}

Categories