How can I write this multiple-count loop as a single query? - php

I'm really stumped here, I've tried using:
sum(case when date_format(from_unixtime(l.date_updated), '%Y-%m-%d') = date_format(now(), '%Y-%m-%d') then 1 else 0 end) AS day0_leads,
in my query, and it did not work as intended, so I ended up using this:
<?php
$total_days = '14';
for ($i = $total_days - 1; $i >= 0; $i--)
{
$day = strtotime('-'.$i.' days');
$day_string = date('n/j', $day);
$leads = mysql_result(mysql_query("select count(*) from `leads` where date_format(from_unixtime(`date_updated`), '%m-%d-%Y') = date_format(from_unixtime($day), '%m-%d-%Y')"), 0);
$assigns = mysql_result(mysql_query("select count(*) from `assigns` where date_format(from_unixtime(`date_assigned`), '%m-%d-%Y') = date_format(from_unixtime($day), '%m-%d-%Y') and `id_dealer` not in (1,2,3)"), 0);
echo "['$day_string', $leads, $assigns]";
if ($i > 0)
echo ',';
}
?>
It is making the page load slow, obviously due to unnecessary queries. What is the proper way of writing this as a single query and outputting the results? Like I said, I've tried a sum with a then else, and it did not product the correct numbers.
Any help would greatly be appreciated.

Heres my solution:
$total_days = '14';
// get leads count array
$sql = mysql_query("select count(*) as `count`, `date_updated`
from `leads`
where date_format(from_unixtime(`date_updated`), '%Y-%m-%d') >= date_format(now() - interval $total_days day, '%Y-%m-%d')
group by date(from_unixtime(`date_updated`));") or die(mysql_error());
$leads_count = array();
while ($row = mysql_fetch_assoc($sql))
$leads_count[date('n/j', $row['date_updated'])] = $row['count'];
// get assigns count array
$sql = mysql_query("select count(*) as `count`, `date_assigned`
from `assigns`
where date_format(from_unixtime(`date_assigned`), '%Y-%m-%d') >= date_format(now() - interval $total_days day, '%Y-%m-%d') and `id_dealer` not in (1,2,3,4)
group by date(from_unixtime(`date_assigned`));") or die(mysql_error());
$assigns_count = array();
while ($row = mysql_fetch_assoc($sql))
$assigns_count[date('n/j', $row['date_assigned'])] = $row['count'];
for ($i = $total_days - 1; $i >= 0; $i--)
{
$day = strtotime('-'.$i.' days');
$day_string = date('n/j', $day);
$leads = ((empty($leads_count[$day_string])) ? '0' : $leads_count[$day_string]);
$assigns = ((empty($assigns_count[$day_string])) ? '0' : $assigns_count[$day_string]);
echo "['$day_string', $leads, $assigns]";
if ($i > 0)
echo ',';
}

Related

Not able to pass array data

I am trying to create an array in $data, but it is not happening. I am using this code to make a day wise sale chart.
$data = array();
for ($i = 0; $i <= 10; $i++) {
$billdate = date('d-m-Y', strtotime("-$i day"));
$sqlQuery = "select sum(amount),bill_date from msr_bills WHERE bill_date='$billdate' ";
$result = mysqli_query($con, $sqlQuery);
$fetchamount = mysqli_fetch_row($result);
$sum = $fetchamount[0];
$data = new \stdClass();
$data->bill_date = $billdate;
$data->amount = $sum;
$report_JSON = json_encode($data);
echo $report_JSON.",";
}
You can merge your loop into one query, and then iterate over the results instead:
$data = array();
$billdate = date('Y-m-d', strtotime('-10 day'));
$sqlQuery = "SELECT bill_date, SUM(amount) AS amount
FROM msr_bills
WHERE bill_date >= '$billdate'
GROUP BY bill_date";
$result = mysqli_query($sqlQuery);
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
$data[] = (object)$row;
}
$report_JSON = json_encode($data);
echo $report_JSON;
}
Note that your date format is not compatible with MySQL dates, which are stored in Y-m-d format, and I have changed that in the code. If your bill_date column is actually a text field stored in d-m-Y format, you will need to convert it in the query like so:
$sqlQuery = "SELECT bill_date, SUM(amount) AS amount
FROM msr_bills
WHERE STR_TO_DATE(bill_date, '%d-%m-%Y') >= '$billdate'
GROUP BY bill_date";
Note also that you can in fact do the computation of $billdate internal to your SQL query using date arithmetic:
$sqlQuery = "SELECT bill_date, SUM(amount) AS amount
FROM msr_bills
WHERE STR_TO_DATE(bill_date, '%d-%m-%Y') >= CURDATE() - INTERVAL 10 DAY
GROUP BY bill_date";
And if you are running MySQL 8.0+, you can do the entire operation in MySQL:
$sqlQuery = "SELECT JSON_ARRAYAGG(data) AS data
FROM (SELECT JSON_OBJECT('bill_date', bill_date, 'amount', SUM(amount)) AS data
FROM msr_bills
WHERE bill_date >= CURDATE() - INTERVAL 10 DAY
GROUP BY bill_date) d";
$result = mysqli_query($sqlQuery);
if ($result) {
$row = mysqli_fetch_assoc($result);
$report_JSON = $row['data'];
echo $report_JSON;
}
Demo on dbfiddle
Put your echo outside loop. remove code $report_JSON = json_encode($data);
$respnseArr = array();
{
.
.
.
$respnseArr[] = $data;
}
echo json_encode($respnseArr);

mysql select each day record for the last 7 days

how do you select each day records for the last 7 days? if the dates are not available set it to 0. I tried the below but I am not getting any results.
$stmt = $db->prepare("SELECT DATE(order_date),COUNT(id) as 'total' FROM `orders` WHERE `order_date` BETWEEN DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND CURDATE()GROUP BY DATE(order_date)");
$stmt->execute();
$result = $stmt->get_result();
$total = [];
while($row = $result->fetch_object()){
$total[] = $row->total;
}
print_r($total);
not the actual solution I wanted but I managed to get the results by wrapping the query in a function and calling it 7 times...
function weeklyData($day){
$stmt = $db->prepare("SELECT order_date from orders where DATE(FROM_UNIXTIME(order_date)) = CURDATE() - INTERVAL ? DAY");
$stmt->bind_param('s', $day);
$stmt->execute();
$stmt->store_result();
return $stmt->num_rows;
}
$total = [];
for($x = 1; $x <= 7; $x++){
$total[] = weeklyData($x);
}
print_r($total);

Wanted to find the number of present days using php?

Hi to all the people here in stackoverflow, I would just like to ask for a little help from you guys. I'm stuck on what I'm doing I wanted to count the number of days present in my query but I don't know how. Could anyone help me on this? An form of help would be much appreciated.
Here is my codes with comments:
//Used for getting the values
$mfrom = $this->input->get('mfroma'); //From: Month
$yfrom = $this->input->get('yfroma'); //From: Year
$yto = $this->input->get('ytoa'); //To : Year
$n_of_months = $this->input->get('n_of_monthsa'); // Month or year Range
$cmonth = $mfrom; //From: Month
$cyear = $yfrom; //From: Year
$clastyear = $yto; //To: Year
$sSQLSelect = "";
$sSQLSelect1 = "";
for($i=0;$i<=$n_of_months;$i++)
{
$curdate = $cmonth." ".$cyear;
$sSQLSelect = $sSQLSelect."SUM(IF(DATE_FORMAT(date_d, '%c %Y') = '$curdate' ,
IF(DP.hrsdiff <= 4, 0.5, 1), 0)) AS 'month$cmonth$cyear', ";
$sSQLSelect1 = $sSQLSelect1."month$cmonth$cyear + ";
if($cmonth+1 > 12) {
$cyear++;
$cmonth = 1;
} else
$cmonth++;
}
date_default_timezone_set('Asia/Manila');
$current_date = date('Y-m',time());
$d = array();
$i = 0;
$sSQL = "SELECT TS.id AS TSid, employeeid, `date` AS date_d, TS.TI1 AS TI1, TS.TO1 AS TO1,
CONCAT(E.lastName,', ',E.firstName,' ',E.middleInitial,'.') AS 'fullname',
(TIME_TO_SEC(CAST(TS.`TI1` AS time))/3600) AS 'timeinint',
(TIME_TO_SEC(CAST(TS.`TO1` AS time))/3600) AS 'timeoutint',
E.startDate, C.companyName, B.branchName,
R.mon, R.tue, R.wed, R.thu, R.fri, R.sat, R.sun
FROM timeschedule AS TS
LEFT JOIN employee AS E ON TS.employeeid = E.id
LEFT JOIN company AS C ON E.companyid = C.id
LEFT JOIN branch AS B ON E.branchid = B.id
LEFT JOIN restday AS R ON R.id = E.restDayid
WHERE TS.`show` = '1' $namecondition $companynamecondition $branchnamecondition
GROUP BY employeeid
ORDER BY fullname ASC";
$result = $this->db->query($sSQL);
$data = array();
foreach($result->result() as $row)
{
$rowemployeedetails = $row;
$fullname = $row->fullname;
$startdate = $row->startDate;
$st_month = (int)(date("m",strtotime($startdate)));
$st_day = (int)(date("d",strtotime($startdate)));
$st_year = (int)(date("Y",strtotime($startdate)));
$data['data'][$i][] = array($row->fullname);
$data['data'][$i][] = array($row->companyName);
$data['data'][$i][] = array($row->branchName);
// #$cmonth = start_month
// #$cyear = start_year
// #number months in between
$cmonth = $mfrom;
$cyear = $yfrom;
for($j=0; $j<= $n_of_months ;$j++){
if((date('Y-m', strtotime($startdate)) <= date('Y-m', strtotime($cyear.'-'.$cmonth)))&&($current_date >= date('Y-m', strtotime($cyear.'-'.$cmonth))))
{
$d[$j] = ((date('Y-m', strtotime($cyear.'-'.$cmonth)) == date('Y-m',time()))?date('d', time()):cal_days_in_month(CAL_GREGORIAN, $cmonth, $cyear));
}
else
{
$d[$j]=0;
}
if($cmonth === 12){
$cyear++;
$cmonth = 1;
}
else{
$cmonth++;
}
}
// #Result: d[] = number of days in month
// #$cyear = start year filter
// #$clastyear = last year filter
// #$cmonth = start_month
$cyear = $yfrom;
$clastyear = $yto;
}
$result->free_result();
return json_encode($data);
}
If you have two dates and want to know the amount of days from one to the other, a simple solution would be to use DateTime::diff like so:
<?php
$from = new DateTime('2014-03-28');
$to = new DateTime('2014-03-30');
$interval = $from->diff($to);
echo $interval->format('%R%a'); // +2

MySQL Query – is there a better way?

On my blog I am have a function that counts how many blog posts have been made month by month and these can be displayed in a sub menu.
It is looped by year, and then another nested loop by month. Each time it runs this query to count how many articles were posted in each month.
This is the query:
Select * from DM_blog blog where blog.id IN
( SELECT entry_id FROM DM_tags_target tagstarget WHERE tagstarget.parent_id IN
( SELECT id FROM DM_tags tags WHERE tags.tag = '".$data['page']['id']."' AND tags.type = 'blog_target' )) AND blog.publish < '".date("Y-m-d H:i:s")."' and blog.status = '0' and YEAR(blog.publish) = '".$year."' and MONTH(blog.publish) = '".$month."'"
Is there a better way to do this? Can I do all of the months at once instead of having to do 12 queries a year? The full code is here:
$this->benchmark->mark('blog_submenu_start');
$dates = $this->blog_model->menu_dates($data);
if($dates['years']){
$i = 0;
foreach($dates['years'] as $year){
if($data['segments']['modal'] == $year['YEAR(blog.publish)']){
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['class'] = 'selected';
$selected = true;
}else if(date("Y") == $year['YEAR(blog.publish)'] && $selected == false){
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['class'] = 'selected';
$selected = true;
}
// find the start month
if($dates['first_entry'][0]['YEAR(blog.publish)'] == $year['YEAR(blog.publish)']){
if($dates['first_entry'][0]['MONTH(blog.publish)'] < 2){
$limit_s['start'] = '1';
$limit_s['end'] = 13;
}else{
$limit_s['start'] = $dates['first_entry'][0]['MONTH(blog.publish)'];
$limit_s['end'] = 12;
}
}else{
$limit_s['start'] = 1;
$limit_s['end'] = 13;
}
// run through the months
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_start');
for($x=$limit_s['start'];$x<=$limit_s['end'];$x++){
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_start');
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_mysql_start');
$count = $this->blog_model->month_count($year['YEAR(blog.publish)'],$x,$data);
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_mysql_end');
if($last == false){
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_selected_start');
if($data['segments']['modal'] == $year['YEAR(blog.publish)'] and $data['segments']['para_one'] == $x){
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['months'][$x]['class'] = 'selected';
}
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_selected_end');
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_assign_start');
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['months'][$x]['month'] = $x;
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['months'][$x]['display_full'] = date('F',strtotime($year['YEAR(blog.publish)'].'-'.$x.'-01'));
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['months'][$x]['display_short'] = date('M',strtotime($year['YEAR(blog.publish)'].'-'.$x.'-01'));
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['months'][$x]['count'] = $count;
$data['date_submenu']['year'][$year['YEAR(blog.publish)']]['months'][$x]['sef'] = $year['YEAR(blog.publish)'].'/'.$x.'/';
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_assign_end');
if(date("Y") == $year['YEAR(blog.publish)'] and date("m") == $x || date("n") == $x){
$last = true;
} // end date
$i++;
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_'.$x.'_end');
} // end last false
} // end for
$this->benchmark->mark('blog_submenu_dates_'.$year['YEAR(blog.publish)'].'_end');
}
}
$this->benchmark->mark('blog_submenu_end');
$this->blog_model->month_count - this function is as follows:
function month_count($year,$month,$data=false){
$query = $this->db->query("Select * from DM_blog blog where blog.id IN
( SELECT entry_id FROM DM_tags_target tagstarget WHERE tagstarget.parent_id IN
( SELECT id FROM DM_tags tags WHERE tags.tag = '".$data['page']['id']."' AND tags.type = 'blog_target' )) AND blog.publish < '".date("Y-m-d H:i:s")."' and blog.status = '0' and YEAR(blog.publish) = '".$year."' and MONTH(blog.publish) = '".$month."'");
return $query->num_rows();
}
You can add group by clause to group the results by year and month.
Select * from DM_blog blog where blog.id IN
( SELECT entry_id FROM DM_tags_target tagstarget WHERE tagstarget.parent_id IN
( SELECT id FROM DM_tags tags WHERE tags.tag = '".$data['page']['id']."' AND tags.type = 'blog_target' )) AND blog.publish < '".date("Y-m-d H:i:s")."' and blog.status = '0' GROUP BY YEAR(blog.publish), MONTH(blog.publish)
You could use a GROUP BY expression:
SELECT id, YEAR(blog.publish), MONTH(blog.publish)
FROM DM_blog blog
WHERE blog.id IN
( SELECT entry_id
FROM DM_tags_target tagstarget
WHERE tagstarget.parent_id IN
( SELECT id
FROM DM_tags tags
WHERE tags.tag = '".$data['page']['id']."'
AND tags.type = 'blog_target'
)
)
AND blog.publish < '".date("Y-m-d H:i:s")."'
AND blog.status = '0'
GROUP BY YEAR(blog.publish), MONTH(blog.publish)
It will give you the results grouped by year and month

Calculating max logins for each day

I have a database full of php time(); stored when a user logs in.
I know I should have created a value for their username and updated the login count but instead I have a database full of php time(); with their username
Here is how I find the amount of logins for individual users:
<?php
function to_date($timestamp) {
return date('Y-m-d', $timestamp);
}
$days = array();
$occurences = array();
$zero = array();
$query = mysql_query("SELECT `login_time` FROM `stats` WHERE `userid`='$someuserid' ORDER BY `login_time` ASC");
while($rows = mysql_fetch_array($query)) {
$days[] = to_date($rows['login_time']);
}
$days[] = to_date(time());
$occurences = array_count_values($days);
$days = array_unique($days);
sort($days);
for($i = 0; $i < count($days); $i++) {
$difference = isset($days[$i+1]) ? strtotime($days[$i+1]) - strtotime($days[$i]) : 0;
if($difference > 86400) {
$difference = ceil(abs($difference/86400));
$fill = $days[$i];
for($k = 0; $k < $difference-1; $k++) {
$fill += strtotime('+1 day', strtotime($fill));
$zero[] = to_date($fill);
}
}
}
echo "[";
for($i = 0; $i < count($zero); $i++) {
echo "[\"".$zero[$i]."\",0], ";
}
for($i = 0; $i < count($occurences); $i++) {
if($i == count($occurences)-1)
echo "[\"".$days[$i]."\",".($occurences[$days[$i]]-1)."]";
else {
echo "[\"".$days[$i]."\",".$occurences[$days[$i]]."], ";
}
}
echo "]";
?>
How could I apply this to all the users and find out who logged in the most for each day in the database? The output is encoded for jqplot.
SELECT
userid,
DATE(FROM_UNIXTIME(login_time-MOD(login_time,86400)+1)) as logindate,
count(*) as logincount
FROM stats
GROUP BY userid, logindate
Use the above query to get all the required data directly from the database and this will help you avoid doing the post processing using PHP
Additionally, if you would like to get only one record, which have maximum logins in a (any) day, the use the below query with an added SQL wrapper for the above query:
SELECT * FROM (
SELECT
userid,
DATE(FROM_UNIXTIME(login_time-MOD(login_time,86400)+1)) as logindate,
count(*) as logincount
FROM stats
GROUP BY userid, logindate
) tmptable
ORDER BY logincount DESC, logindate DESC LIMIT 1
Let me know if this helped you.
SELECT userid, COUNT(userid) AS 'login_count' FROM stats GROUP BY userid
All the answer may be correct or incorrect. But I know one thing that my answer is not correct.But in the case of Max logins , there is no need of such an answer. Thats all I know.

Categories