I'm retrieving some data from a database where the values might be something like the following:
Column1 | Column2
-----------------
Bob | 24
Joe | 17
Jimmy | 38
Joe | 10
Bob | 5
Sam | 8
With this data, I want to somehow select the Bob rows and multiply them together. I want to do this for all rows that match in Column1. I'm not concerned about doing it in SQLite, but what is the best way to go about this in PHP? I've currently added the results to an array in PHP by doing the following:
$myArray[$resultRow['Column1']] = $resultRow['Column2'];
I was wondering how to go about navigating through this and finding matching keys, multipying their values together, and outputting something like
Column1 = Column2-a * Column2-b
consider this code:
$results = array();
foreach(array('Bob' => 24, 'Joe' => 17, 'Jimmy' => 38, 'Joe' => 10, 'Bob' => 5, 'Sam' => 8) as $key => $val){
$results[$key][] = $val;
}
echo '<pre>';
print_r($results);
echo '</pre>';
out put:
Array
(
[Bob] => Array
(
[0] => 5
)
[Joe] => Array
(
[0] => 10
)
[Jimmy] => Array
(
[0] => 38
)
[Sam] => Array
(
[0] => 8
)
)
PHP ignores duplicate key, you have to create $results array when you retreiving the data from database, lets assume that you do like this:
while () {
$col1 = $row["col1"];
$col2 = $row["col2"];
$results[$col1][] = $row["col2"];
}
now the results array must be like this:
Array
(
[Bob] => Array
(
[0] => 24
[1] => 5
)
[Joe] => Array
(
[0] => 17
[1] => 10
)
[Jimmy] => Array
(
[0] => 38
)
[Sam] => Array
(
[0] => 8
)
)
now, its easy to search for colmun1 names like this:
$values_for_colmn1 = $results[$column1]; //which is an array
// use array_product() function for array product
$product_for_column1 = array_product($values_for_colmn1);
First, to read only Bob's values:
$stmt = $db->prepare('SELECT Column2 FROM MyTable WHERE Column1 = ?')
$stmt->bindValue(1, 'Bob', SQLITE3_TEXT);
$result = $stmt->execute();
Then, multiply all of them:
$value = 1.0;
while ($res = $result->fetchArray()) {
$value = $value * $res['Column2'];
}
Related
How can I get and assign a random array value from array inside a while loop to a variable?
Code
$stmt = $pdo->prepare("SELECT mem_id FROM members WHERE mem_id NOT IN (SELECT ref_referral FROM referrals)");
$stmt-> execute();
$rec = array();
while($f = $stmt->fetch()){
$rec[] = $f;
}
print_r($rec);
The above code returns this array
Array
(
[0] => Array
(
[mem_id] => 2
[0] => 2
)
[1] => Array
(
[mem_id] => 3
[0] => 3
)
[2] => Array
(
[mem_id] => 4
[0] => 4
)
)
Now if I want to take one value from either of 2,3,4 randomly and assign it to a variable say $randomValue = $randomValueFromArray, how can I do that?
Suppose that I have a table like this:
id name age birthplace
------------------------------
1 John 28 NY
2 Marry 23 LD
3 Mohamad 34 Malaysia
...
I do while loop like this:
$query = "SELECT name, age, birthplace FROM tableName";
$result = mysqli_query($dbc, $query);
$tableRows = array();
while($rows = mysqli_fetch_array($result, MYSQLI_ASSOC)){
$tableRows[] = $rows;
}
echo '<pre>';
print_r($tableRows);//Print the table rows from array
echo '</pre>';
I've got:
Array
(
[0] => Array
(
[name] => John
[age] => 28
[birthplace] => NY
)
[1] => Array
(
[name] => Marry
[age] => 23
[birthplace] => Prozent Rabatt
)
[2] => Array
(
[name] => 45521
[age] => Bekleidung
[birthplace] => LD
)
[3] => Array
(
[name] => Mohamad
[age] => 34
[birthplace] => Malaysia
)
)
I would like to change the keys name, age, birthplace to 0, 1, 2 respectively.
I have read this link:
In PHP, how do you change the key of an array element?
But it seems that I do not need it as the function because it looks so advanced to me.
I also read this link:
PHP rename array keys in multidimensional array
But it just meant to change one key in one array only as I tested for my case.
Your help is appreciated.
Thanks,
using MYSQLI_ASSOC its return associative array if you replace it with MYSQLI_NUM in mysqli_fetch_array() it will return a result as you ask
$query = "SELECT name, age, birthplace FROM tableName";
$result = mysqli_query($dbc, $query);
$tableRows = array();
while($rows = mysqli_fetch_array($result,MYSQLI_NUM)){
$tableRows[] = $rows;
}
echo '<pre>';
print_r($tableRows);//Print the table rows from array
echo '</pre>';
My code looks like this:
$sql = $pdo->prepare('SELECT source_clicks,source_impr,source_spend FROM `statistic` WHERE camp_id =? AND date BETWEEN ? AND ?');
$sql->bindColumn('source_clicks',$source_clicks);
$sql->bindColumn('source_impr',$source_impr);
$sql->bindColumn('source_spend',$source_spend);
$sql->execute([$_POST['get_source_stat'],$date[0],$date[1]]);
while ( $sql->fetch()) {
$data = explode(',',$source_clicks);
print_r($data);
}
the output i get is:
Array ( [0] => 30 [1] => 30 [2] => 51 [3] => 108 ) Array ( [0] => 30 [1] => 30 [2] => 51 [3] => 228 )
i need to sum this arrays saving their keys and get something like this:
array ([0] => 60 [1] => 60 [2] => 102 [3] => 336)
Can you tell me how can i do it?
One way to do this would be to push each exploded $source_clicks value into an array, and then use array_sum and array_column to get the results e.g.
$data = array();
while ($sql->fetch()) {
$data[] = explode(',',$source_clicks);
}
$sums = array();
foreach (array_keys($data[0]) as $column) {
$sums[$column] = array_sum(array_column($data, $column));
}
print_r($sums);
I've got a database table that looks like this:
uid | group | category
1 | group1 | cat1
2 | group1 | cat2
3 | group2 | cat3
4 | group2 | cat4
5 | group2 | cat5
6 | group3 | cat6
7 | group3 | cat7
But I need this data in an array, that groups categories by their group.
For example, my array should look like this:
Array
(
[group1] => Array
(
[0] => Array
(
[0] => 1
[1] => cat1
)
[1] => Array
(
[0] => 2
[1] => cat2
)
)
[group2] => Array
(
[0] => Array
(
[0] => 3
[1] => cat3
)
[1] => Array
(
[0] => 4
[1] => cat4
)
[2] => Array
(
[0] => 5
[1] => cat5
)
)
[group3] => Array
(
[0] => Array
(
[0] => 6
[1] => cat6
)
[1] => Array
(
[0] => 7
[1] => cat7
)
)
)
I've written a foreach loop that does just this, but I have a problem.
My problem is that it always leaves out the very last row of the table, and I'm not sure how to fix it. In my mind, the logic dictates that it should always work.
I was thinking that after the loop I could just add the very last row to the new array, but I think that may cause issues if the last row has a different group, and I would rather the solution be built into the foreach loop.
Unfortunately, I am at a loss here. How can I fix my code to include the very last row of the database query?
I would also be interested to see what improvements I can make on my current code, but that may be a better question for codereview.
My loop:
$pass = [];
foreach($stmt as $key => $value) {
if(empty($currentGroup)) $currentGroup = $value['group'];
if(empty($temp)) $temp = [];
if($currentGroup != $value['group'] || $key+1 == count($stmt)) {
$pass[$currentGroup] = $temp;
$currentGroup = $value['group'];
$temp = [];
$temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']];
} else {
$temp[] = [$stmt[$key]['uid'], $stmt[$key]['category']];
}
}
The following should do it:
<?php
//Create an array to store our grouped rows
$grouped = array();
//Loop over all rows returned by the $stmt that has been executed.
//You could probably remove the key from here, it's not needed it seems.
//The keys within the $value array will match the names of the columns in
//the database,
foreach($stmt as $key => $value){
//As we're storing by the group value from the row we first want to
//check if our grouped array contains a key for the group of the row
//being processed. If it does not, create an empty array within the
//grouped data for this group.
if(!array_key_exists($value['group'], $grouped)){
$grouped[$value['group']] = array();
}
//Knowing we will always have an array element for the rows group
//we can blindly append the values for this row to the grouped
//container using its values.
//'[] =' is just short hand append.
$grouped[$value['group']][] = array(
$value['uid'],
$value['category']
);
}
Hope that helps!
To further future proof this loop you could change the grouped value append to the following:
<?php
//Setting the whole row (minus the group) rather than just the uid
//and category explicitly allows this code to work without modification
//as the datatable changes, ie. new columns. Assuming that is the 'group'
//column remains present
unset($value['group']);
$grouped[$value['group']][] = $value;
Grouped contents data could now be accessed using the following:
<?php
//Acceess data via column name not array index, yay!
echo $grouped['group1']['uid']
I've needed this again recently, so I made a function based around #JParkinson1991's answer.
I'm putting this here for documentation, and to possibly help future readers.
function groupArray($arr, $group, $preserveSubArrays = false, $preserveGroupKey = false) {
$temp = array();
foreach($arr as $key => $value) {
$groupValue = $value[$group];
if(!$preserveGroupKey)
{
unset($arr[$key][$group]);
}
if(!array_key_exists($groupValue, $temp)) {
$temp[$groupValue] = array();
}
if(!$preserveSubArrays){
$data = count($arr[$key]) == 1? array_pop($arr[$key]) : $arr[$key];
} else {
$data = $arr[$key];
}
$temp[$groupValue][] = $data;
}
return $temp;
}
Breakdown
function groupArray($arr, $group, $preserveGroupKey = false, $preserveSubArrays = false)
This function accepts 2 to 4 parameters.
The flat array you want to group (array)
The key you want to group by (string/int)
Option to preserve the group key in the output of each sub array (Boolean)
Option to preserve sub arrays. If only 1 key exists in each sub array, the function will store just the single value for each row instead of an array (Boolean)
The first parameter is the array itself, the second parameter is the key that you want to group by, and the 3rd (optional) parameter is a boolean that tells the function if you want to preserve the group key in the sub arrays.
$temp = array();
foreach($arr as $key => $value) {
$groupValue = $value[$group];
if(!$preserveGroupKey)
{
unset($arr[$key][$group]);
}
if(!array_key_exists($groupValue, $temp)) {
$temp[$groupValue] = array();
}
$temp[$groupValue][] = $arr[$key];
}
First, we create a temporary array called $temp
Next, we loop through the array grabbing the key (Which should be a string or int), and the value (Which should be an array).
We set $groupValue to whatever the value is of the $group you chose, such as "group" in the example below.
$arr = [
0 => [
"group" => "group1",
"name" => "Bob",
],
1 => [
"group" => "group1",
"name" => "Randy",
],
2 => [
"group" => "group1",
"name" => "Susan",
],
3 => [
"group" => "group2",
"name" => "Larry",
],
4 => [
"group" => "group2",
"name" => "David",
],
5 => [
"group" => "group3",
"name" => "Perry",
],
];
Then we check if we want to $preserveGroupKey's. If this boolean is false (And it is by default), the key will be removed leaving several subarrays with just the "name" key left.
Now we check if the $groupValue exists in our $temp array, if it does not, we create it.
Then we add to the $temp[$groupValue] whatever the current row values are. From the example above, we would end up with:
Array
(
[group1] => Array
(
[0] => Bob
[1] => Randy
[2] => Susan
)
[group2] => Array
(
[0] => Larry
[1] => David
)
[group3] => Array
(
[0] => Perry
)
)
Or, with the 3rd parameter set to true you would get:
Array
(
[group1] => Array
(
[0] => Array
(
[name] => Bob
)
[1] => Array
(
[name] => Randy
)
[2] => Array
(
[name] => Susan
)
)
[group2] => Array
(
[0] => Array
(
[name] => Larry
)
[1] => Array
(
[name] => David
)
)
[group3] => Array
(
[0] => Array
(
[name] => Perry
)
)
)
I am trying to get values from MySQL array as alphabetically, and I want results like:
[B] => Array (
[id] => 6
[firstname] => Bon
[lastname] => Jone
),
Array (
[id] => 7
[firstname] => bon
[lastname] => doe
)
[H] => Array
(
[id] => 1
[firstname] => Hassan
[lastname] => Ilyas
)
[J] => Array
(
[id] => 5
[firstname] => John
[lastname] => Doe
)
Here is the code of what I have tried.
edited
$result = mysqli_query($GLOBALS['conx'],"SELECT * FROM $users_table ORDER BY firstname ASC");
while ($row = mysqli_fetch_assoc($result)) {
extract($row);
$row['alphabets'] = ucfirst($firstname[0]);
$data[] = $row;
}
But it outputs like this:
[0] => Array
(
[id] => 6
[firstname] => Bon
[lastname] => Jone
)
[1] => Array
(
[id] => 7
[firstname] => bon
[lastname] => doe
)
[2] => Array
(
[id] => 1
[firstname] => Hassan
[lastname] => Ilyas
)
[3] => Array
(
[id] => 5
[firstname] => John
[lastname] => Doe
)
How can I get output like this:
A
Adam Smith
Alan smith
B
Bone Doe
Bone Joe
J
John Smith
.... etc
ucfirst returns the entire string with the first letter capitalised, you'll need to grab just the first letter with substr first.
$data = [];
while ($row = mysqli_fetch_assoc($result)) {
extract($row);
$key = strtoupper($firstname[0]))
$data[$key][] = $row;
}
To get the output (roughly) like you want, try something like:
foreach ($data as $letter => $rows)
{
echo "<h1>{$letter}</h1>", PHP_EOL;
foreach ($rows as $row)
{
echo "<p>{$row['firstname']} {$row['lastname']}</p>", PHP_EOL;
}
}
Your attempt will not do what you want. To achieve this, you will have to create a nested array, then on each iteration check the first letter of the firstname. Check if that letter already exists as a key in the array, and create an item in your array with an empty array as its value, it if it doesn't, and then add the row data to it to that newly created empty array.
$data = [];
while ($row = mysqli_fetch_assoc($result)) {
$firstLetter = strtoupper($row["firstname"][0]); // convert to upper case so all are the same
if (array_key_exists($firstLetter, $data) === false) $data[$firstLetter] = [];
// now just add the row data:
$data[$firstLetter][] = $row;
}
First use Order in your MySQL Query: ... ORDER BY firstname ASC
Create Arrays for Alphabets using PHP:
$Alphabetic_Array = array();
while ($row = mysqli_fetch_assoc($result)) {
$Alphabetic_Array[$row['firstname'][0]][] = $row;
}
First of all, I suggest you to sort records in your query, otherwise you have to sort resulting array before grouping it:
SELECT * from tablename
ORDER BY firstname ASC, lastname ASC
Then, you can use array_map to group your array:
$result = array();
array_map
(
function( $row ) use( &$result )
{
$result[strtoupper(substr($row['firstname'],0,1))][] = $row;
},
$data
);
(Note that we have to call $result by reference)
Now the $result is an array like this:
Array
(
[B] => Array
(
[0] => Array
(
[id] => 7
[firstname] => bon
[lastname] => doe
)
[1] => Array
(
[id] => 6
[firstname] => Bon
[lastname] => Jone
)
)
[H] => Array
(
[0] => Array
(
[id] => 1
[firstname] => Hassan
[lastname] => Ilyas
)
)
[J] => Array
(
[0] => Array
(
[id] => 5
[firstname] => John
[lastname] => Doe
)
)
)
If you want/can use PDO instead of mysqli_, you can obtain desired result directly from MySQL query. Set your query in this way:
SELECT UPPER(SUBSTR(firstname,1,1)) as initial, tablename.* from tablename
ORDER BY firstname ASC, lastname ASC
and then, fetching in in this way:
$data->fetchAll( PDO::FETCH_ASSOC|PDO::FETCH_GROUP );
your $data will contain desired array, without need of additional processing.
The PDO::FETCH_GROUP option groups fetched results by first column returned by query, in your case the capitalized firstname first letter.
What about letting MYSQL do the logic?
SELECT * FROM users_table, SUBSTRING(firstName, 1, 1) as initial ORDER BY firstname ASC
Then you just can append each line to an array
while ($row = mysqli_fetch_assoc($result)) {
$Alphabetic_Array[$row['initial'] = $row;
}
It's just pseudo code but I think the idea is pretty clear