Currently I am collecting a count of desktop and mobile devices... the count is coming back correctly based in the items total in the ARRAY. But, now I need to remove duplicates... Example user_id = 001 can have 10 entries for IOS ... so I would need to do something like ... IF $row['last_login'] Date() is the most current then grab that entry and count as 1. End result for user_id = 001 would be 1 entry count and not 10 (which I am getting now).
if ($results = $dbh->runQuery($sql)) {
foreach ($results as $key=>$row){
$users[$row['user_id']][] = array('user_id'=>$row['user_id'],
'racid' => $row['racid'],
'email' => $row['email'],
'last_login' => $row['last_login'],
'fname' => $row['fname'],
'lname' => $row['lname'],
'role_id' => $row['role_id'],
'role_name' => $row['role_name'],
'ios_device_token' => $row['ios'],
'roid_device_token' => $row['roid'],
'p_name' => $row['p_name']);
if($row['ios'] !== null && $row['ios'] !== '' && $row['ios'] !== '-1'){
$ios_count++;
}
if($row['android'] !== null && $row['android'] !== '' && $row['android'] !== '-1'){
$android_count++;
}
$invalidValues = [null, "", -1];
if(in_array($row['ios'], $invalidValues) && in_array($row['android'], $invalidValues)){
$desktop_count++;
}
}
}
Using associative arrays, you can "distinctify" by your own criterium. Something like the following code.
However what #esqew said (commenting your question) about altering the SQL instead of the PHP is probably a cleaner angle, especially since PHP is generally quite slow.
if ($results = $dbh->runQuery($sql)) { // that exists already
$latestEntries = []; // assoc. array: key=user, value=row
foreach ($results as $row) { // that exists already
// assuming 'last_login' is a timestamp or any format that can be used in inequality
// otherwise cook your own comparison function
if (
!$latestEntries[$row['user_id']]
|| $latestEntries[$row['user_id']]['last_login'] < $row['user_id']['last_login']
) {
$latestEntries[$row['user_id']] = $row;
}
// rest of your code that exists already
}
// here, after the loop, $latestEntries has the latest entry for each user found in $results
}
Related
I am doing a count and sum on each item, and need the array to look like this.
[Date] =>
[device_type1] => [all the data]
[device_type2] => [all the data]
Thing is I am doing a search through each and then all of them return a date, I need all of them to be under that one date, and inside that array to hold each of the devices as key and inside that all the information. here is what I have so far.
$all_device_types = array('pole','covert','firewatch','internet','trailer','slave','project');
foreach ($all_device_types as $adt) {
$du->select("CONCAT(YEAR(uptime_date),'-',MONTH(uptime_date),'-',DAY(uptime_date)) as year_month_day,
SUM(uptime_router) as router,
COUNT(uptime_router) as router_count,
uptime_device_type as device_type,
date(uptime_date) as data_date","
WHERE uptime_device_type = '".$adt."'
GROUP BY CONCAT(YEAR(uptime_date),'-',MONTH(uptime_date),'-',DAY(uptime_date))
ORDER BY uptime_date ASC");
$all_results = array();
while( $all_row = $du->fetch() ){
if ($adt == $all_device_types[0]) {
$dates[] = $all_row['data_date'];
$adt_0 = $all_row;
} elseif ($adt == $all_device_types[1]) {
$adt_1[] = $all_row;
} elseif ($adt == $all_device_types[2]) {
$adt_2[] = $all_row;
} elseif ($adt == $all_device_types[3]) {
$adt_3[] = $all_row;
} elseif ($adt == $all_device_types[4]) {
$adt_4[] = $all_row;
} elseif ($adt == $all_device_types[5]) {
$adt_5[] = $all_row;
} elseif ($adt == $all_device_types[6]) {
$adt_6[] = $all_row;
}
}
}
One of the results looks like this.
[pole] => Array
(
[year_month_day] => 2017-9-5
[router] => 4408
[router_count] => 4620
[device_type] => pole
[data_date] => 2017-09-05
)
It looks like it could be simplified quite a bit. Instead of looping over the device types and running a separate query for each one, you can just add the device type to your GROUP BY and get all your results in a single query.
I think CONCAT(YEAR(uptime_date),'-',MONTH(uptime_date),'-',DAY(uptime_date)) should output the same thing as date(uptime_date), and you should be able to use the aliases in your GROUP BY and ORDER BY clauses.
$du->select("DATE(uptime_date) as data_date,
uptime_device_type as device_type,
SUM(uptime_router) as router,
COUNT(uptime_router) as router_count,
GROUP BY data_date, device_type
ORDER BY data_date, device_type");
If I'm mistaken and you do need the CONCAT version, add it back in of course, but the main thing is adding device_type to the GROUP BY and eliminating the WHERE clause.
Then as you fetch your results, you can insert them directly into the multidimensional structure you want.
while( $row = $du->fetch() ) {
$all_results[$row['data_date']][$row['device_type']][] = $row;
// to calculate totals for all the devices for each date
if (!isset($all_results[$row['data_date']]['all_devices']) {
// initialize if not set
$all_results[$row['data_date']]['all_devices'] = [
'router' => 0, 'router_count' => 0];
}
// increment values
$all_results[$row['data_date']]['all_devices']['router'] += $row['router'];
$all_results[$row['data_date']]['all_devices']['router_count'] += $row['router_count'];
}
I'm having trouble trying to remove null values from an array using values from the database. These null values are usually found within the 'answers'.. Code below:
$getQuestions = mysql_logging_query("SELECT fq.`question_id`, fq.`ques_form_id`, fq.`question_body`, fq.`type`, fq.`answer1`, fq.`answer2`, fq.`answer3`, fq.`answer4`, fq.`answer5`, fq.`answer6`, fq.`min_validation`, fq.`max_validation`
FROM QuestionnaireFormQuestions fq
LEFT JOIN QuestionnaireForms f
ON f.`form_id` = fq.`ques_form_id`
WHERE f.`active` = 1
AND f.`form_id` = '".mysql_real_escape_string($form_id,$this->dbcon)."'
",$this->dbcon);
if($getQuestions && mysql_num_rows($getQuestions)>0 && mysql_error($this->dbcon)=="")
{
$get_questions_array = array();
while($getQuestions && $getQuestions_rec=mysql_fetch_assoc($getQuestions))
{
$get_questions_array[] = array('question_id' => $getQuestions_rec['question_id'],
'related_form_id' => $getQuestions_rec['ques_form_id'],
'question_body' => $getQuestions_rec['question_body'],
'question_type' => $getQuestions_rec['type'],
'possible_answer1' => $getQuestions_rec['answer1'],
'possible_answer2' => $getQuestions_rec['answer2'],
'possible_answer3' => $getQuestions_rec['answer3'],
'possible_answer4' => $getQuestions_rec['answer4'],
'possible_answer5' => $getQuestions_rec['answer5'],
'possible_answer6' => $getQuestions_rec['answer6'],
'min_validation' => $getQuestions_rec['min_validation'],
'max_validation' => $getQuestions_rec['max_validation']
);
}
if(is_array($get_questions_array) && count($get_questions_array)>0)
{
foreach($get_questions_array as $key=>$array)
{
if($array === null) {
unset($get_questions_array[$key]);
}
$return['data']['questions'][] = $array;
}
}
}
else
//error
A return for example; would look like this:
"question_id":"3",
"related_form_id":"4",
"question_body":"Do you like this content?",
"question_type":"radio",
"possible_answer1":"Disagree",
"possible_answer2":"Neutral",
"possible_answer3":"Agree",
"possible_answer4":null,
"possible_answer5":null,
"possible_answer6":null,
"min_validation":"1",
"max_validation":"1"
I've tried unsetting the key using empty and isnull but to no avail. Any help would be appreciated.
You are not testing the values inside the array, you need to:
foreach($get_questions_array as $array){
foreach($array as $key=>$element){
if($element===null)
unset($array[$key]);
}
$return['data']['questions'][] = $array;
}
I think it's possible you're looping through your nested data structure at the wrong level.
You have this $get_questions_array, each element of which is an associative array that came from one row in your MySQL result set. But your php code loops over the rows of the result set, not over the columns.
I think you want something more like this, with another nested foreach.
if(is_array($get_questions_array) && count($get_questions_array)>0)
{
foreach($get_questions_array as $row)
{
foreach ($row AS $colname=>$colvalue)
{
if ($colvalue === null || $colvalue =='')
{
unset($row[$colname]);
}
}
}
}
See what's going on? Your code was throwing away whole rows that were null, but there weren't any of those, so it wasn't doing anything.
why don't you query the data that does not contain nulls, instead of removing the nulls by yourself ? let the database do this for you something like:
select * from table where possible_answer IS NOT NULL
Try this loop through the array and set them to null with the key's if the value is empty
foreach($getQuestions_rec as $key => $value){
if($value == ''){
$getQuestions_rec[$key] = null;
}
}
Use the IFNULL(ColumnName,"") to replace the null values to empty string in SQL query.
Example: IFNULL(answer6,"")
refer this this How to remove null values from an array? or you ca alter the query to select the null values from table.
I have database that contains scores which are stored daily. I want to average each months scores for each user. So far I have this:
DB structure:
id | name | tscore | added
int| string | float(100 or less)| date(2014-01-01 16:34:22)
Code:
while($row = mysql_fetch_assoc($getChartData)){ // Data from MySQL
$added_date = explode(' ',$row['added']); // Date formate 2014-01-01 16:34:22
$chartData[] = array(
'id' => $row['name'],
'tscore' => $row['tscore'],
'added' => $added_date[0] // Here I take the month only
);
}
if($_POST['range'] == 'month'){
foreach($chartData as $key => $value){
$added = explode('-',$chartData[$key]['added']);
$count = 1;
foreach($chartData as $key2 => $value2){
$added2 = explode('-',$chartData[$key2]['added']);
if($chartData[$key]['id'] === $chartData[$key2]['id'] && $added[1] === $added2[1]){ // if user is the same and the month is the same, add the scores together, increment counter, and unset 2nd instance
$chartData[$key]['tscore'] = ((float)$chartData[$key]['tscore'] + (float)$chartData[$key2]['tscore']);
$count++;
unset($chartData[$key2]);
}
}
$chartData[$key]['tscore'] = ($chartData[$key]['tscore']/$count); // Average all the scores for the month.
}
}
The problem is this method is deleting all the elements of the $chartData array. What can I try to resolve this?
You should try to solve it with MySQL. Try something like this (replace 'your_scores_table' with your table name):
SELECT
Score.name,
AVG(Score.tscore) AS `avg`,
CONCAT(YEAR(Score.added), '-', MONTH(Score.added)) AS `year_month`
FROM
your_scores_table AS Score
GROUP BY
Score.name ASC,
YEAR(Score.added) DESC,
MONTH(Score.added) DESC
;
Your logic is wrong. You are looping through the same array twice. Which means that the following if will always evaluate to true which means that array item will always get unset
//This will always be true
if($chartData[$key]['id'] === $chartData[$key2]['id'] && $added[1] === $added2[1]){
It may be simpler for you to create another array where you keep your scores. Something like
$aScores = array();
$count = 1;
foreach($chartData as $key => $value){
//Add score to a different array
$aScores[$value['name']]['tscore'] = (($aScores[$value['name']]['tscore'] + $value['tscore']) / $count);
$count++;
}
Also I would look into the MySQL AVG function. You could use that to save you having to do it in PHP
I would like to grab the values of several textarea fields and save them to the database. For now I have four of each with different values and I want to batch save these values, the textarea fields are:
<textarea name="compedia[]"></textarea>
<textarea name="specification[]"></textarea>
and the save function:
function saveCOA(){
$labref=$this->uri->segment(3);
$data= $this->input->post('compedia');
$data1= $this->input->post('specification');
$compedia=array(
'labref'=>$labref, //NDQA201303001
'compedia'=>$data,
'specification'=>$data1
);
foreach ($compedia as $value) {
$this->db->insert('coa_body',$value);
}
}
When I print_r($value) it returns :
NDQA201303001
Array ( [0] => Alphy [1] => poxy [2] => alphy [3] => poxy )
Array ( [0] => poxy [1] => alphy [2] => poxy [3] => alphy )
and when I try to save, it returns:
A Database Error Occurred
Error Number: 1054
Unknown column 'NDQA201303001' in 'field list'
INSERT INTO `coa_body` (`NDQA201303001`) VALUES ('')
Filename: C:\xampp\htdocs\NQCL\system\database\DB_driver.php
Line Number: 330
How should the syntax be so as to loop over all the textarea values and save them to the database at once?
I hope that
count($data) == count($data1); //Always True!
If that's the case the following will work:
for ($i=0;$i<count($data);$i++) {
$insert_data = array(
'labref'=>$labref, //NDQA201303001 - Same for all the rows
'compedia'=>$data[$i],
'specification'=>$data1[$i]
);
$this->db->insert('coa_body',$insert_data);
}
Check this Link: CodePad.org
Update:
Suggested by Rcpayan:
//This will reduce number of context switching,
//even though loping is doubled!
for ($i=0;$i<count($data);$i++) {
$insert_data[$i] = array(
'labref'=>$labref, //NDQA201303001
'compedia'=>$data[$i],
'specification'=>$data1[$i]
);
}
$this->db->insert_batch('coa_body',$insert_data);
You could do something like this, it's a bit longer but can also deal with compedia and specification not being equal. This solutions assumes a few things:
You want the value of labref to be the same for each row inserted
If the number of values for compedia and specification aren't equal, you still want to insert the row, but the 'missing' values will be set to NULL.
$labref = $this->uri->segment(3);
$compedia_data = $this->input->post('compedia');
$specification_data = $this->input->post('specification');
//Calculate which array is larger, so we can loop through all values
$max_array_size = max(count($compedia_data), count($specification_data));
//Iterate through the arrays
for ($i = 0; $i < $max_array_size; $i++)
{
$this->db->set('labref', $labref);
//If we still have a value(s) for compedia, then assign the value, otherwise set to NULL
if array_key_exists($i, $compedia_data)
{
$this->db->set('compedia', $compedia_data[$i]);
}
else
{
$this->db->set('compedia', NULL);
}
//If we still have a value(s) for specification, then assign the value, otherwise set to NULL
if array_key_exists($i, $specification_data)
{
$this->db->set('specification', $specification_data[$i]);
}
else
{
$this->db->set('specification', NULL);
}
//Insert into table: 'coa_body'
$this->db->insert('coa_body');
}
Alternatively, you could change the loop to assign the values to an array, then batch insert these values. This might offer better performance.
//Initial other relevant code is included in the example above (excluded here for brevity)
$insert_array = new array();
//Iterate through the arrays
for ($i = 0; $i < $max_array_size; $i++)
{
$row_array = new array();
$row_array['labref'] = $labref;
//If we still have a value(s) for compedia, then assign the value, otherwise set to NULL
if array_key_exists($i, $compedia_data)
{
$row_array['compedia'] = $compedia_data[$i];
}
else
{
$row_array['compedia'] = NULL;
}
//If we still have a value(s) for specification, then assign the value, otherwise set to NULL
if array_key_exists($i, $specification_data)
{
$row_array['specification'] = $specification_data[$i];
}
else
{
$row_array['specification'] = NULL;
}
//Add current row to the insert array, so it can be added to the database
$insert_array[$i] = $row_array;
}
//Insert into table: 'coa_body'
$this->db->insert_batch('coa_body', $insert_array);
I am attempting to identify whether a variable in an array is present, and if it is state that it is "true" and if it is not state that it is "false". The problem is that I am receiveing a response for all array variables, when I only want to know if the page variable is present in the array with link like http://example.com/product.php?image_id=50
<?php
$page = $_GET['image_id'];
if (!empty($_SESSION)){
foreach($_SESSION as $name => $value2) {
if (substr($name, 0, 7)=='images_') {
$id = substr($name, 7, (strlen($name)-7));
$get = mysql_query('SELECT * FROM images WHERE image_id='.mysql_real_escape_string((int)$id));
while ($cart_info_row = mysql_fetch_assoc($get)) {
$cart = array('image_id' => $cart_info_row['image_id'],);
if (in_array($page, $cart)){echo 'true';} else {echo 'false';}
}
}
}
}
}
?>
Assuming the numbers below are in the SESSION print_r ($cart):
Array ( [image_id] => 42 ) false
Array ( [image_id] => 45 ) false
Array ( [image_id] => 50 ) true
Array ( [image_id] => 49 ) false
Now, how can I ONLY identify if variable 50 ($page = $_GET['image_id'];)is present with out the other three?
As I understand, your code does 2 things: 1 - checks if key images_$page exists in session and 2 - checks if image with image_id=$page exists in database.
<?php
$page = $_GET['image_id'];
if(isset($_SESSION['images_'.$page]))
{
$get = mysql_query("SELECT * FROM images WHERE image_id='".mysql_real_escape_string($page)."' LIMIT 1");
if($cart_info_row = mysql_fetch_row($get))
{
echo 'true';
}
else
{
echo 'false';
}
}
else
{
echo 'false';
}
Here isset is used to check if the key images_$page exists in $_SESSION. It is faster than making 2 calls to substr() function.
Also, since we need only checking if given image exists, foreach loop is replaced with if.
After that, a MySQL query runs, and since we need only first match, LIMIT 1 is added to make query faster. Also comparison with image_id is already included in query, so its enough to test if there are returned rows or not (that's why original while is replaced with if).