I have data coming back from MySQL and the goal is to pull data from multiple servers.
The data can be grouped by one or more fields, and I want to pull data from X number of MySQL servers and sum the data that should be summed, using the other data as a key or index.
Example:
Result from Mysql[$x]:
[{"date":"2017-10-10","account":"1","trees":"1","people":"0","pets":"4"}
,{"date":"2017-10-10","account":"2","trees":"2","people":"5","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"3","people":"3","pets":"4"}
,{"date":"2017-10-11","account":"2","trees":"4","people":"1","pets":"4"}]
Result from Mysql[$x+1]:
[{"date":"2017-10-10","account":"1","trees":"5","people":"1","pets":"1"}
,{"date":"2017-10-10","account":"2","trees":"5","people":"2","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"5","people":"0","pets":"2"}
,{"date":"2017-10-11","account":"2","trees":"5","people":"1","pets":"2"}]
Desired end result:
[{"date":"2017-10-10","account":"1","trees":"6","people":"1","pets":"5"}
,{"date":"2017-10-10","account":"2","trees":"7","people":"7","pets":"2"}
,{"date":"2017-10-11","account":"1","trees":"8","people":"3","pets":"6"}
,{"date":"2017-10-11","account":"2","trees":"9","people":"2","pets":"6"}]
in this case, there are 2 keys, date and account, but in reality there can be between 1 and 4.
The grouping keys are known, so the code knows that in this case, date and account are the keys.
I'm trying to find a better way than iterating through each row of mysql[$x] and then iterating through each row of mysql[$x+1] ... mysql[$x+n] and checking each value of the known keys to see if they match the current row's key values and then summing the data.
Also note that in reality, there may not be a row for each set of keys, hence the number and order of rows from each server can be variable.
I need an efficient way to do this because there are potentially tens of thousands of rows with a dozen+ columns.
I'm experimenting with code like this:
$res = array();
$keys = array('date','account');
array_walk($t,'rehash',$res);
function rehash($data,$key,&$result) {
global $keys;
global $res;
$keydata = array_slice($data,0,count($keys));
$vals = array_slice($data,count($keys));
//this is how the data would ideally be structured, my model
//$res[$keydata[$keys[0]]][$keydata[$keys[1]]] = $vals;
//this code below successfully creates rows in the right format
for($x = count($keys) - 1; $x>= 0; $x--) {
if($x == count($keys)-1) {
$tmp = array($keydata[$keys[$x]] => $vals);
//} else if($x ==0) {
// maybe reconcile here?
} else {
$tmp = array($keydata[$keys[$x]] => $tmp);
}
}
}
But how do i reconcile this? I can't simply do $res[key1] = $tmp[key1] because with multiple keys it would remove all the other rows.
Also with nested arrays, how would I iterate through each nested array if the number of levels is variable?
Lastly if I do this, I would need to convert it back into the original format for the frontend, so... joy. :D (this part would be easy, just is worth taking into consideration from an efficiency standpoint)
You don't need to use array_walk, since your data isn't hierarchical. Just use an ordinary foreach loop.
$res = array();
foreach ($t as $row) {
$cur = &$res;
// Drill down into result array using the key fields, creating nested arrays
// as necessary
foreach ($keys as $keycol) {
$key = $row[$keycol];
if (!isset($cur[$key])) {
$cur[$key] = array();
}
$cur = &$cur[$key];
}
// Now go through the data columns in the row, adding them to the totals
foreach ($row as $key => $val) {
if (in_array($key, $keys)) {
// Put the key fields in the result row
$cur[$key] = $val;
} else {
// Accumulate other values in the result row
if (!isset($cur[$key])) {
$cur[$key] = 0;
}
$cur[$key] += $row[$key];
}
}
unset($cur); // Break the reference link
}
Here is a possible solution based on the structure of the sample data given in the question.
$jsn1 = '[{"date":"2017-10-10","account":"1","trees":"1","people":"0","pets":"4"}
,{"date":"2017-10-10","account":"2","trees":"2","people":"5","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"3","people":"3","pets":"4"}
,{"date":"2017-10-11","account":"2","trees":"4","people":"1","pets":"4"}]';
$jsn2 = '[{"date":"2017-10-10","account":"1","trees":"5","people":"1","pets":"1"}
,{"date":"2017-10-10","account":"2","trees":"5","people":"2","pets":"1"}
,{"date":"2017-10-11","account":"1","trees":"5","people":"0","pets":"2"}
,{"date":"2017-10-11","account":"2","trees":"5","people":"1","pets":"2"}]';
/* Decode the json strings into associative arrays: */
$arr1 = json_decode($jsn1, true);
$arr2 = json_decode($jsn2, true);
/* Put in an array the keys whose values are to be added: */
/* Do not include date and account keys if they are not to be added */
$arr_keys = ['trees', 'people', 'pets'];
/* Loop through both $arr1 and $arr2 while storing new arrays in arr: */
/* Be adding up the values for the keys that are in $arr_keys */
$arr = [];
foreach($arr1 as $k => $v){
$arr[$k]['date'] = $arr1[$k]['date']; $arr[$k]['account'] = $arr1[$k]['account'];
foreach($arr_keys as $y){
if($arr1[$k][$y] !== null && $arr2[$k][$y] !== null){
$arr[$k][$y] = $arr1[$k][$y] + $arr2[$k][$y];
}}}
/* encode the array to the required json string: */
$json = json_encode($arr);
echo $json;
/* Output:
[{"date":"2017-10-10","account":"1","trees":"6","people":"1","pets":"5"}
,{"date":"2017-10-10","account":"2","trees":"7","people":"7","pets":"2"}
,{"date":"2017-10-11","account":"1","trees":"8","people":"3","pets":"6"}
,{"date":"2017-10-11","account":"2","trees":"9","people":"2","pets":"6"}]
*/
I have a simple question. I have an array that has two columns (id, name) that is a result of a MySQL query. I want to store the result of the query into a array variable so i can access each element when i need to.
I am able to store a one dimension array like the following:
$array = array();
while($row = mysqli_fetch_assoc($result))
{
$array[] = $row['name'];
}
How can I store and access a two dimensional array? Also is it best to use a for loop or while loop to store these?
Simply do this:
$array = array();
while($row = mysqli_fetch_assoc($result))
{
$array[] = $row;
}
To access your results you can do this:
$firstResultRow = $array[0];
$firstResultName = $array[0]['id'];
$firstResultName = $array[0]['name'];
This will tell you if a particular row exists:
if(isset($array[$x])) {
$aRow = $row[$x];
// do stuff with $aRow;
}
This will give you a row count for your array:
$rowCount = count($array);
This will set up a loop through your array:
foreach($array as $index => $row) {
$id = $row['id']
$name = $row['name'];
// $index will have the array index of the current row. 0 -> $rowCount - 1
}
Don't specifically store the index of $row but rather store the whole row.
$array = array();
while($row = mysqli_fetch_assoc($result))
{
$array[] = $row;
}
Then $array will have the following structure:
$array = [
[
'id'=> ...,
'name' => ...,
],
...
];
To initially access all of the results from [mysqli_fetch_assoc][1] you will want to use the while loop like you are, mysqli_fetch_assoc will continue to output results until it doesn't have any more data. Then at that point mysqli_fetch_assoc will return NULL. This will signal to your while loop to stop iterating.
Then to access variables inside of your $array, I recommend using foreach.
You could then do:
foreach ($array as $row) {
do something with $row['name'] or $row['id']
}
You could also use a for loop, but it takes more work IMO. Compare the above with this alternative:
for ($i = 0; $i < count($array); $i++) {
$row = $array[$i];
do something with $row['name'] or $row['id']
}
How do I get all the values from a field in a record in an Array?
I want to make an average from a numerical score held under a specific field in an Array. The array is pulled from a form. Here is what I have so far but it just doesn't work.
$records = get_field('maths_month_report'); //gets all the records
$progressscore = $records['progress']; //targets the specific field in those records
echo . array_sum($progressscore)/count($progressscore) .; //divides the numbers in the field by the amount of records
revision: My apologies for not mentioning that the records are Arrays within the 'maths_month_report' Array. I can target specific fields in specific records with:
$firstrecord = $records[0];
$output = $firstrecord['progress'];
I just want to target all the 'progress' values so i can average them.
Based on your comments, if these are arrays within an array, you would need to build a new array:
$progresscore = array_column($records, 'progress')
PHP < 5.5:
$progresscore = array_map(function($item) {
return $item['progress'];
}, $records);
Or, just iterate yourself:
$sum = $count = 0;
foreach ($records as $record) {
$sum += $record['progress'];
++$count;
}
echo $sum / $count;
I wish to run a foreach on a load of ID's.
However each of the items in the foreach is a select query and if it finds more ID's they need to be added to the array that is being run in the foreach.
E.g
$ids = array();
foreach($ids as $id)
{
SELECT id FROM table WHERE otherid = $id;
foreach ($query2->result_array() as $row)
{
array_push($array, $row['id']);
}
}
This is obviously pseudocode so no need to correct my SQL etc. I just need for the foreach to continue if it finds more ID's.
Possible?
I have tried adding an & here -> foreach($ids as &$id) as somebody else on here has suggested in a similar question. This doesn't seem to work.
foreach actually makes a copy of your array to loop though, you will need to use while.
while(list($id_key, $id) = each($ids)){
//your code
$ids[] = $row[id];
}
You should simply be able to just reference the original array ie
foreach ($query2->result_array() as $row)
{
$id[] = $row;
}
This will automatically assign an auto incremented key to the the new array element and add it to the $id array. I assume this is what you are after.
Try to iterate with a variable:
$ids = array();
$i = 0;
while ($i < count($ids)) {
$query2->query(SELECT id FROM table WHERE otherid = $ids[$i]);
foreach ($query2->result_array() as $row)
$ids []= $row['id'];
$i++;
}
For similar problems, I have always used two different arrays. Such code can run a query for every id only one time. I don't think it would be possible with only one array+foreach;
The following code is pretty simple. It keeps finding new ids until there are no new ids.
$ids = array();
$new = array();
$new = $ids;
do {
foreach($new as $n) {
$new = array();
//// HERE PUT YOUR CODE TO RUN A QUERY AND MAYBE PUSH A NEW ID TO $new \\\\
}
$ids = array_merge($ids,$new);
} while (count($new)!==0);
I am fetching data from my DB and they look like this:
[{"0":"1","key-1":"1","1":"1","key-2":"1","2":"1","key-3":"1","3":"1","key-4":"1"}]
where the key-1 are the name of the column. (I only have one entry so).
I want to extract only the column values and save them into a new array that will output like this:
{"key-1":"1","key-2":"1","key-3":"1","key-4":"1"}
I want it to look exactly like this and not : [{"key-1":"1","key-2":"1","key-3":"1","key-4":"1"}]
I tried this:
$cart["key-1"]=$output["key-1"];
where $output is the outcome of the DB that shown first (the one with []).
and the $cart is the new array I want.
Both are declared as:
$cart=array();
$output=array();
and $output[]=$row where row is the result of the DB fetch. How to do it?
Here's one way to do it, I've substituted the database row for a string here, and made use of json_decode() and json_encode()
$data = '[{"0":"1","key-1":"1","1":"1","key-2":"1","2":"1","key-3":"1","3":"1","key-4":"1"}]';
// convert to an array
$data = json_decode($data, true);
// create new array here
$cart = array();
for ($i = 0; $i < count($data); $i++)
{
foreach ($data[$i] as $k => $v)
{
if (strpos($k, 'key') !== FALSE)
{
$cart[$k] = $v;
}
}
}
echo $cart['key-1'] . '<br/>';
echo json_encode($cart);
Output:
1
{"key-1":"1","key-2":"1","key-3":"1","key-4":"1"}
This is a very chaotically asked question.
From what I gathered you want maybe this..?
$cart=array();
foreach ($output as $index=>$value){
if stripos($index,"key-"){
cart[$index]=$value;
}
}
Use mysql_fetch_assoc() to get only column names ;)
while ($row = mysql_fetch_assoc($result_of_query))
{
echo $row['key-1'];
echo $row['key-2'];
}