I am doing the following queries on a database that holds various customers orders.
SELECT WEEKDAY(orderDateTime) Date, COUNT(clientID) totalCount FROM orders WHERE YEARWEEK(orderDateTime,1) = YEARWEEK(NOW(),1) GROUP BY DATE(orderDateTime)
SELECT WEEKDAY(orderDateTime) Date, COUNT(clientID) totalCount FROM orders WHERE YEARWEEK(orderDateTime,1) = YEARWEEK(NOW() - INTERVAL 1 WEEK,1) GROUP BY DATE(orderDateTime)
SELECT DATE_FORMAT(orderDateTime, '%Y') as 'year', DATE_FORMAT(orderDateTime, '%m') as 'month', COUNT(clientID) as 'total' FROM orders GROUP BY DATE_FORMAT(orderDateTime, '%Y%m')
I am them building these into an array with the month/ day numbers against the counted value:
[[0, 1], [1,4]...]
I am using Flot to graph these but what is happening is that any days or months that there are no orders it has no values (Obviously) so what you get is something like this:
[[0, 1], [1,4], [6,12]] which makes the graph plot wrong.
What trying to work out is how to pad it so it looks like:
[[0, 1], [1,4], [2,0], [3,0], [4,0], [5,0], [6,12]] <-- For the week days and,
[[1, 1], [2,4], [3,0], [4,0], [5,0], [6,0], [7,12], [8,0], [9,12], [10,0], [11,0], [12,0]] <-- for each month.
Im using PHP as the main grunt. Any pointers would be appreciated and sorry if I'm not that clear. Ask if you need any clarification.
PHP:
$thisWeekA = array();
$thisWeekQ = $database->query("SELECT WEEKDAY(orderDateTime) Date, COUNT(clientID) totalCount FROM orders WHERE YEARWEEK(orderDateTime,1) = YEARWEEK(NOW(),1) GROUP BY DATE(orderDateTime)")->fetchAll();
foreach($thisWeekQ as $thisweek){
$thisWeekA[] = array( $thisweek['Date'], $thisweek['totalCount'] );
}
array(2) {
[0]=>
array(4) {
["Date"]=>
string(1) "2"
[0]=>
string(1) "2"
["totalCount"]=>
string(1) "3"
[1]=>
string(1) "3"
}
[1]=>
array(4) {
["Date"]=>
string(1) "3"
[0]=>
string(1) "3"
["totalCount"]=>
string(1) "2"
[1]=>
string(1) "2"
}
}
for weekly data use for loop in your php update it as,
Logic only 7 days in a week of instead of using foreach from the result data we can use the for loop for seven days
i.e., similarly use for years also
$thisWeekA = array();
$thisWeekQ = $database->query("SELECT WEEKDAY(orderDateTime) Date, COUNT(clientID) totalCount FROM orders WHERE YEARWEEK(orderDateTime,1) = YEARWEEK(NOW(),1) GROUP BY DATE(orderDateTime)")->fetchAll();
for ($i = 0; $i <= 6; $i++) {
if ($thisWeekQ[$i]['Date'] == $i) {
$thisWeekA[$i][] = array($thisWeekQ[$i]['Date'], $thisWeekQ[$i]['totalCount']);
} else {
$thisWeekA[$i][] = array($i, 0);
}
}
You might want to think about building your arrays more like this:
var dow = [];
dow[0] = 1;
dow[1] = 4;
dow[6] = 12;
At this point you can populate your array for your chart
var chartData = [];
for (var i=0; i<7; i++){
chartData[i] = [i, (dow[i] === undefined ? 0 : dow[i])];
}
I managed to figure out a way of doing this. Thanks for pointing me in the direction of the For loop!
This is what I have came up with and works!
function arrayhunt($products, $field, $value){
foreach($products as $key => $product){
if ($product[$field] == $value){
return $key;
}
}
return false;
}
$i = 0;
for ($i = 0; $i <= 6; $i++) {
$keys = arrayhunt($thisWeekQ,"Date",$i);
if($keys !== FALSE){
$thisWeekA[] = array($thisWeekQ[$keys]['Date'], $thisWeekQ[$keys]['totalCount']);
} else {
$thisWeekA[] = array($i, 0);
}
$keys = "";
}
Hopefully someone finds this useful later.
Related
I'm trying to sum values from the array from certain ranges provided by another array.
I've tried with this function
function sumArray($array, $min, $max) {
$sum = 0;
foreach ($array as $k => $v) {
if ($k >= $min && $k <= $max) {
$sum += $v;
}
}
return $sum;
}
and this works if i hardcode numbers of course, but i can't figure out how to make this work in a loop
So I have this dates array
array(3) {
["June"]=> int(4)
["July"]=> int(31)
["August"]=> int(29)
}
and i have this daily_values array
array(64) {
[0]=> int(8)
[1]=> int(6)
[2]=> int(10)
[3]=> int(15)
[4]=> int(10)
[5]=> int(9)
[6]=> int(9)
.
.
.
[63] => int(10)
Now what I want to do here is:
based on how many entries are in for example June which is 4 in this case I want to get the sum of values in daily_values array like this:
first loop iteration will sum values in daily_values array from 0 to 3, the second loop iteration will sum values from 4 to 34 and third loop iteration will sum values from 35 to 63 and so on and so on.
So the final thing I want from all this is to have an array which will be like this
["sum of 0,3", "sum of 4,34", "sum of 35,63"]
Just a note here, this array is much bigger, but I cut it short just for question purposes.
I tried to understand your question and here is what I think you are trying to achieve.
I created a similar test and it works fine. Hope it helps you in someway.
<?php
$june = [1,1,1,1];
$july = [1,1];
$august = [1,1,1,1];
$months = array(
'June' => $june,
'July' => $july,
'August' => $august,
);
$daily = [1,1,1,1,5,5,10,10,10,10,2,2,2,2,2];
$sum_arr = array();
$i = 0;
foreach($months as $key=>$month){
$month_count = $month;
$month_sum = 0;
while($month_count > 0){
$month_sum += $daily[$i];
$i++;
$month_count--;
}
$sum_arr[$key] = $month_sum;
}
echo '<pre>';
print_r($sum_arr);
?>
Its my first time working with multidimensional arrays in php. I need to change the second number in each sub array.
What I want is to check if the Id in the array matches the Id from the database. When the two match I want to change the 2nd entry in the sub array by adding a number to it. If the Id from the query does not match anything in the list I want a new sub array to be pushed to the end of the array with the values of Id and points_description.
Also, if its helpful, my program right now does find the matches. The only thing is, it does not update the 2D array.
$array = array(array());
while ($row_description = mysqli_fetch_array($query_description)) {
$check = 1;
$is_match = 0;
foreach ($array as $i) {
foreach ($i as $value) {
if ($check == 1) {
if ($row_description['Id'] == $value) {
//$array[$i] += $points_description;
$is_match = 1;
}
}
$check++;
$check %= 2; //toggle between check and points
}
}
if ($is_match == 0) {
array_push($array, array($row_description['Id'], $points_description));
}
}
I feel like Im doing this so wrong. I just want to go through my 2D array and change every second value. The expected output should be a print out of all the Ids and their corresponding point value
I hope this is helpful enough.
Example: $row_description['Id'] = 2 and $array = array(array(2,1), array(5,1) , array(6,1))
output should be $array = array(array(2,4), array(5,1) , array(6,1))
if $row_description['Id'] = 3 and $array = array(array(2,1), array(5,1) , array(6,1))
output should be $array = array(array(2,4), array(5,1) , array(6,1),array(3,3))
By default PHP will copy an array when you use it in a foreach.
To prevent PHP from creating this copy you need to use to reference the value with &
Simple example :
<?php
$arrFoo = [1, 2, 3, 4, 5,];
$arrBar = [3, 6, 9,];
Default PHP behavior : Make a copy
foreach($arrFoo as $value_foo) {
foreach($arrBar as $value_bar) {
$value_foo *= $value_bar;
}
}
var_dump($arrFoo);
/* Output :
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
*/
ByReference : Don't create the copy :
foreach($arrFoo as &$value_foo) {
foreach($arrBar as $value_bar) {
$value_foo *= $value_bar;
}
}
var_dump($arrFoo);
/* Output :
array(5) {
[0]=>
int(162)
[1]=>
int(324)
[2]=>
int(486)
[3]=>
int(648)
[4]=>
&int(810)
}
*/
I have this PHP code, with a for loop:
$expireData = array();
for($x = 0; $x <= 10; $x++){
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from users WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
$row = $stmt->fetchAll();
#var_dump($row);
if($row["cnt"] > 0){
$expireData[] = $row["cnt"];
}else{
$expireData[] = 0;
}
}
If I do the var_dump($row) I get:
array(2) {
[0]=>
array(4) {
["days"]=>
string(2) "27"
[0]=>
string(2) "27"
["cnt"]=>
string(1) "2"
[1]=>
string(1) "2"
}
[1]=>
array(4) {
["days"]=>
string(3) "116"
[0]=>
string(3) "116"
["cnt"]=>
string(1) "8"
[1]=>
string(1) "8"
}
}
But if I just echo $row['cnt']; it doesn't echo anything out - it's empty. Why?
Ultimately, I wish to use the data from the for loop outside the for loop - like:
echo implode(',', $expireData);
But that just gives me
0,0,0,0,0,0,0,0,0,0
What am I doing wrong?
Because you're using fetchAll() to retrieve all rows into $row, its contents are a 2 dimensional array representing multiple rows. So the key ['cnt'] is present, but is one dimension farther in your array.
$row['cnt'] doesn't exist but $row[0]['cnt'] does and $row[1]['cnt'] do exist.
The simplest solution with your current code is to move the $expireData handling outside the loop and into a loop of its own:
$expireData = array();
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from users WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
// Load all rows into $rows rather than $row...
$rows = $stmt->fetchAll();
// Loop over all rows to populate $expireData
foreach ($rows as $row) {
if ($row["cnt"] > 0){
$expireData[] = $row["cnt"];
}else{
$expireData[] = 0;
}
}
print_r($expireData);
The other method would be to switch from fetchAll() to plain fetch() and append rows onto $rows in a while loop:
// Array to hold all rows
$rows = array();
// (The outer for loop is removed...)
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from users WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
// Perform single fetch() calls in a while loop
while ($row = $stmt->fetch()) {
// Append onto array of all rows
$rows[] = $row;
// Then handle $expireData in the same loop
if ($row["cnt"] > 0){
$expireData[] = $row["cnt"];
}else{
$expireData[] = 0;
}
}
Pad the array to 10 values:
As determined in the comments, you need your final $expireData array to have 10 values. Rather than doing that with a loop, use array_pad() to extend it to ten and fill it with zeros.
$expireData = array_pad($expireData, 10, 0);
// turns [2,8] into [2,8,0,0,0,0,0,0,0,0]
Notes on the for loop:
The use of the outer for look is suspect because it is apparently executing the same statement each time. That loop may be entirely unneeded, and all you need is its body.
Notes on error reporting:
The fact that you did not see PHP complaining about undefined index 'cnt' while loading the loop suggests that you are not developing with display_errors turned on and error_reporting turned up. Always do so when developing and testing code. It may have helped you see the problem sooner.
At the top of your script:
error_reporting(E_ALL);
ini_set('display_errors', 1);
Hi I am trying to count the number of duplicate values in a associative array that looks like this:
array(3) { [0]=> array(3) { ["Title"]=> string(25) "hello"
["Price"]=> int(50)
["Count"]=> int(1) }
[1]=> array(3) { ["Title"]=> string(35) "world"
["Price"]=> int(50)
["Count"]=> int(1) }
[2]=> array(3) { ["Title"]=> string(25) "hello"
["Price"]=> int(50)
["Count"]=> int(1) } }
As you can see here there is a duplicate value in the "Title" lable I want to count them and add one to the "Count" part. I started to do something like this:
$prodArray = array();
// Add the values to the array if it's the first time it occurs.
if (!in_array($row['prodTitle'], $prodArray["Title"]))
{
array_push($prodArray,
array( Title => $row['prodTitle'],
Price => $row['prodPrice'],
Count => 1)
);
}
else
{
//Add one to the count for the current item.
}
the thing is I can't access the "Title" element in the array through the in_array function. Any suggestions are welcome.
If you want to detect dups in an array that you are creating, something like this avoid having to go through the array multiple times:
$arr=array();
while($row = mysql_fetch_array($result)) {
$arr[$row['prodTitle']] = isset($arr[$row['prodTitle']])
? $arr[$row['prodTitle']] +1
: 0;
}
$dups = array_keys(array_filter($arr)); //any key => 0 will be filtred out
If you want to just get the dups directly by SQL, have a look at this:
Your current query--
SELECT prodTitle
FROM product
WHERE prodTitle != '{$keyword}'
AND creditCard IN( SELECT creditCard FROM product WHERE prodTitle ='{$keyword}');
which given data like this
prod cc
A 1
A 2
A 3
A 1
A 1
B 15
B 1
B 2
B 21
C 10
C 1
returns this set (with $keyword=='A'):
prod
B
B
C
An aggregate query that returns only records where credit cards used on non-X were also used on X at least twice --
SELECT p1.prodTitle, COUNT(p2.creditCard) AS numrecords
FROM product p1
JOIN product p2
ON (p1.creditCard = p2.creditCard)
WHERE p1.prodTitle != '{$keyword}'
AND p2.prodTitle = '{$keyword}'
GROUP BY p1.prodTitle
HAVING COUNT(p2.creditCard) > 1;
given the same data, returns this set:
prod num
B 2
Doing an aggregate query avoids all the messing about with loops. Here's a link to the MySQL list of aggregate functions.
Okey so I found my solution and I made it look something like this probably not he most efficient way but it works:
$prodArray = array();
$ar = array();
$query ="THE QUERY";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result))
{
array_push($ar, $row['prodTitle']);
}
function findDuplicates($data,$dupval) {
$nb= 0;
foreach($data as $key => $val)
if ($val==$dupval) $nb++;
return $nb;
}
$uniarr = array_unique($ar);
//Will run the function findDuplicates for each unique title in the array
for ($i = 0; $i < sizeof($uniarr); $i++)
{
$count = findDuplicates($ar, $uniarr[$i]);
array_push($prodArray, array( Title => $uniarr[$i], Count => $count));
}
//Displays 2 of the results in the array
for ($c = 0; $c < 2; $c++)
{
echo "The title:".$prodArray[$c]["Title"]." And the amount:".$prodArray[$c]["Count"];
echo "<br />";
}
So that's pretty much it feel free to post your comments on this and if you have any improvements feel free to post them.
Imagine we have an array of students:
Students: Ben Sam ...
Every student has a group of books at home:
Books:
Sam A B C D
Ben D E F
Ryan A D G D
So in PHP, the $students data structure looks like this:
Array
(
[0] => Array
(
[name] => Joe Smith
[books] => Array
(
[0] => A
[1] => B
[2] => C
)
)
)
We want to count how many times A has been repeated and who owns A B and C etc.
One way to do it in php is to do this:
if (sizeof($potential_entries) > 0) :
for ($j = 0, $potentialsize = sizeof($potential_entries); $j < $potentialsize; ++$j) {
for ($k = 0, $listsize = sizeof($student_book); $k < $listsize; ++$k) {
if ($student_book[$k] == $potential_entry[$k]) :
$match = 1;
$student_book[$k]['like_count']++;
endif;
}
}
This is not very efficient we rather want a map structure or a hashtable, Does php has those structures like perl? or do we have to manually build them.
Edit:
I can see in the PHP that we have associative array? Can you please give an example of that could not find it in the documentation.
for sam:
var_dump($potential_entry):
[0]=>array(2) { ["name"]=> string(1) "A" ["id"]=> string(11) "1348"}
[1]=>array(2) { ["name"]=> string(1) "B" ["id"]=> string(11) "1483"}
[2]=>array(2) { ["name"]=> string(1) "C" ["id"]=> string(11) "13"}
[3]=>array(2) { ["name"]=> string(1) "D" ["id"]=> string(11) "1174"}
That is for Sam, for the rest we have the same structure. so sam is array and books is an array and sam has an array of books.
In this example
D count=3 sam ben ryan
A count=2 sam ryan
etc...
If you have $students as an array, and each entry in this array has an array of books which is called books
$books = array();
for ($i = 0, $count = sizeof($students); $i++) {
foreach ($student[$i]['books'] as $book) {
if (isset($books[$book])) {
$books[$book]++;
} else {
$books[$book] = 1;
}
}
}
Then after this, any $books entry whose count is > 1 is a duplicate, i.e.
foreach ($books as $key => $value) {
if ($value) > 1) {
echo "Book " . $key . " is a duplicate (" . $value . ")";
}
}
$aFullCount = array(); // in this array you will have results of all characters count.
$aCondition = array("A", "B"); // set condition you need to count down here.
$aConditionMatch = array(); // in here you will have all users ids who matched your A + B
if ($aUsers){
foreach ($aUsers as $sUserKey=>$aOneUser){
$aForCondition = array();
if ($aPotentialEntries){
foreach ($aPotentialEntries as $aOnePotentialEntry){
$aForCondition[] = $aOnePotentialEntry["name"];
if (!isset($aFullCount[$aOnePotentialEntry["name"]]))
$aFullCount[$aOnePotentialEntry["name"]] = 1;
else
$aFullCount[$aOnePotentialEntry["name"]]++;
}
}
$aConditionCheck = array_intersect($aForCondition, $aCondition);
if (!array_diff($aConditionCheck, $aCondition))
$aConditionMatch[] = $sUserKey;
}
}