upper limit for active records in codeigniter - php

I have this function in my model the purpose of it is to get the stats of the past 30 days starting from the actual day, it was working fine before i reach 30th day then I found out it is counting from the oldest date, so I flipped the order_by from "ase" to "desc" but it seems still going back and counting before the oldest day and not giving me that data I want, so I'm wondering if there any way using codeigniter and give a starting point for the "limit" which should be the actual date.
function graph_data($id_person)
{
$this->db->limit(30); // get data for the last 30 days including the curent day
$this->db->where('personid',$id_person);
$this->db->order_by('date', 'ase');
$query = $this->db->get('stats');
foreach($query-> result_array() as $row)
{
$data[] = $row;
}
return $data;
}

limit returns in your case the last 30 rows. It has nothing to do with dates, unless you only add a row each day.
try using mysql Between
SELECT DATE_FORMAT(create_date, '%m/%d/%Y')
FROM mytable
WHERE create_date BETWEEN SYSDATE() - INTERVAL 30 DAY AND SYSDATE()
ORDER BY create_date ASC
Source -- https://stackoverflow.com/a/2041619/337055

I finally found the solution by giving a range or days, 29 days before the actual day without using BETWEEN and that works fine
<?php
function graph_data($id_person)
{
$today = date('Y-m-d');
$lastdate = date('Y-m-d', strtotime('-29 days', strtotime($today)));// 30 days ago
$this->db->where('personid',$id_person);
$this->db->where("date <= '$today'");
$this->db->where("date >= '$lastdate'");
$this->db->order_by('date', 'ase');
$query = $this->db->get('stats');
$data = array();
foreach($query-> result_array() as $row)
{
$data[] = $row;
}
return $data;
}

Related

Calculating frequency interval for tasks

I have a cron job that gets results from the DB to check it the interval set by user falls on today's date. I am currently thinking of doing it as below :
Get the time column for the row. Ex:2017-05-25 00:00:00
Get the frequency set. Ex:Every 2 weeks.
Get the current date in above format. Ex:2017-05-31 00:00:00
Get the difference in days. Ex:6 days.
Convert the frequency set to days. Ex:2 weeks = 14 days;
Divide (difference in time(days)) by (frequency in days). Ex:6/14
This way I will only get the result to be true when 2 weeks have passed since the time set. I.e., 14/14, 28/14, 42/14,...
If the frequency is in months, I can start dividing by 30. But somehow this feels like a hacky way of doing it. So my question is if there is better way of doing this calculation to check the difference.
This is what I have done as explained by above example.
` $frequency = ; // Get the relevant fields from db
$today = date(Y-m-d H:i:s);
foreach ($frequency as $key => $value) {
$frequency_in_days;
$frequency_type = $value->type;
$frequency_repeat = $value->repeat;
if($frequency_type == 1){
$frequency_in_days = $frequency_repeat;
} elseif($frequency_type == 2) {
$frequency_in_days = $frequency_repeat * 7;
} elseif($frequency_type == 3) {
$frequency_in_days = $frequency_repeat * 30;
} elseif($frequency_type == 4) {
$frequency_in_days = $frequency_repeat * 365;
}
// Get number of days spent between start_date and today in days.
$interval = date_diff($value->start_date, $today)->format('%a');
$result = $interval % $frequency_in_days;
if ($result == 0) {
// Frequency falls today! Do the job.
}
}`
Note: The cron job runs this script. The script again needs to check if the today falls under the frequency set.
Also for argument's sake, is this the best logic to calculate the difference?
Thank you.
This will work
Table "schedule"
`last_run` timestamp,
`frequency_seconds` int
example query for tasks that should go every two weeks:
SELECT *
FROM schedule
WHERE TIMESTAMPDIFF(last_run, NOW()) >= frequency_seconds
after fetching rows update last_run to NOW()

MySQL - INTERVAL 24 HOUR not working as expected

I am building a chart and for that extracting data from the past 24 hours, 48 hours, 1 week and 2 weeks.
I used INTERVAL statements for this purpose but they are not working as expected. I am using Laravel. Here is the function to extract the data:
public function range($range)
{
$data = new Main();
$data0 = $data->whereRaw('updated_at >= DATE_SUB(NOW(), INTERVAL '.$range.')')->whereRaw('MINUTE(updated_at)>54')->orwhereRaw('MINUTE(updated_at)<6')->where('server_short_name', '=', 'FiveRP')->get();
$data1 = $data->whereRaw('updated_at >= DATE_SUB(NOW(), INTERVAL '.$range.')')->whereRaw('MINUTE(updated_at)>54')->orwhereRaw('MINUTE(updated_at)<6')->where('server_short_name', '=', 'GTALife')->get();
$data2 = $data->whereRaw('updated_at >= DATE_SUB(NOW(), INTERVAL '.$range.')')->whereRaw('MINUTE(updated_at)>54')->orwhereRaw('MINUTE(updated_at)<6')->where('server_short_name', '=', 'GermanV')->get();
return compact('data0', 'data1', 'data2');
}
Here is the function that calls the view:
public function hours24()
{
$t = $this::range('24 HOUR');
return view('chart', $t);
}
But in the chart, I am getting results from 22nd of May as well which is the earliest date on DB. Which means that the code isnt working as expected although it is correct according to me. Is there something I am missing out?
I have found the solution. Actually in my code I am using an 'orwhereRaw' which means that I am implying an OR between all the where statements which is sadly not what I want.

Getting MySQL results based on date by current month in Codeigniter

I currently get the last 30 days results like this.
public function commission_month(){
$status = 'A';
$this->db->select_sum('LenderCommission');
$this->db->where(['Status' => $status ]) ;
$this->db->where('CompletedDate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) ');
$query = $this->db->get('toutcome');
$result = $query->result();
return $result[0]->LenderCommission;
}
What i am really trying to do is get results for this current month.
And then when its the next month , its should do the same.
You can use a "like" query to get the information you need, assuming the dates are stored in a manner you can easily apply a like to.
Basically, the query will be something along the lines of ... AND CompletedDate LIKE 'YYYY-MM-%'... where YYYY and MM are valid year and months. This can be done in CodeIgniter by using the $this->db->like() builder:
$this->db->like('CompletedDate', date('Y-m'));
Your code then being:
public function commission_month(){
$status = 'A';
$this->db->select_sum('LenderCommission');
$this->db->where(['Status' => $status ]) ;
$this->db->like('CompletedDate', date('Y-m'));
$query = $this->db->get('toutcome');
$result = $query->result();
return $result[0]->LenderCommission;
}

How can I get unix times for the start and end of last twelve months in a loop?

I wish to print the totals of a column in my database for each month in the last year. The code I have so far to do this is:
$month = date("n");
$year = date("Y");
$loop = 12;
while($loop>1) {
$first = mktime(0,0,0,$month,1,$year);
$last = mktime(23,59,00,$month+1,0,$year);
$spendingData = mysql_query("SELECT * FROM spending WHERE date BETWEEN $first AND $last") or die(mysql_error());
$totalMonth = 0;
while($spending = mysql_fetch_array($spendingData))
{
$totalMonth = $totalMonth + $spending['amount'];
}
print "£".$totalMonth;
$loop = $loop-1;
print "<br>";
}
My quesiton is how, in the loop, do I adjust the times for each month? I thought about just taking a months worth of seconds away from the timestamps, but as I don't know how many days are in each month I don't think this will work. I also don't think I can just keep taking 1 away from the month figure as this will not account for years. I also don't want to hard code the figures in, as they will change with each new month.
How can I achieve this?
Thank you
You could do this rather trivially in MySQL:
SELECT MONTH(date) AS month, SUM(amount) AS amount
FROM yourtable
WHERE YEAR(date) = $year
GROUP BY MONTH(date)
without ever having to involve PHP for the date manipulation stuff.

Displaying Scheduled Events

I had this problem some years ago and back then I implemented a "different logic" in order to deliver the project but the doubt remains in my mind and hopefully with your help I'll be able to understand it now.
Suppose I have some scheduled events on my database that may or may not spawn over several days:
id event start end
-----------------------------------------------
1 fishing trip 2009-12-15 2009-12-15
2 fishCON 2009-12-18 2009-12-20
3 fishXMAS 2009-12-24 2009-12-25
Now I wish to display the events in a calendar, lets take the month of December:
for ($day = 1; $day <= 31; $day++)
{
if (dayHasEvents('2009-12-' . $day) === true)
{
// display the day number w/ a link
}
else
{
// display the day number
}
}
What query should the dayHasEvents() function do to check if there are (or not) events for the day? I'm guessing SELECT .. WHERE .. BETWEEN makes the most sense here but I've no idea how to implement it. Am I in the right direction?
Thanks in advance!
#James:
Lets say we're on December 19th:
SELECT *
FROM events
WHERE start >= '2009-12-19 00:00:00'
AND end <= '2009-12-19 23:59:59'
Should return the event #2, but returns nothing. =\
You should scratch that approach and grab all events for the given month up front so you only need to perform a single query as opposed to N queries where N is the number of days in the month.
You could then store the returned results in a multidimensional array like so:
// assume event results are in an array of objects in $result
$events = array();
foreach ($result as $r) {
// add event month and day as they key index
$key = (int) date('j', strtotime($r->start));
// store entire returned result in array referenced by key
$events[$key][] = $r;
}
Now you'll have a multidimensional array of events for the given month with the key being the day. You can easily check if any events exist on a given day by doing:
$day = 21;
if (!empty($events[$day])) {
// events found, iterate over all events
foreach ($events[$day] as $event) {
// output event result as an example
var_dump($event);
}
}
You're definitely on the right track. Here is how I would go about doing it:
SELECT *
FROM events
WHERE start <= '2009-12-01 00:00:00'
AND end >= '2009-12-01 23:59:59'
And you obviously just replace those date values with the day you're checking on.
James has the right idea on the SQL statement. You definitely don't want to run multiple MySQL SELECTs from within a for loop. If daysHasEvents runs a SELECT that's 31 separate SQL queries. Ouch! What a performance killer.
Instead, load the days of the month that have events into an array (using one SQL query) and then iterate through the days. Something like this:
$sql= "SELECT start, end FROM events WHERE start >= '2009-12-01' AND end <= '2009-12-31'";
$r= mysql_query($sql);
$dates= array();
while ($row = mysql_fetch_assoc($r)) {
// process the entry into a lookup
$start= date('Y-m-d', strtotime($row['start']));
if (!isset($dates[$start])) $dates[$start]= array();
$dates[$start][]= $row;
$end= date('Y-m-d', strtotime($row['end']));
if ($end != $start) {
if (!isset($dates[$end])) $dates[$end]= array();
$dates[$end][]= $row;
}
}
// Then step through the days of the month and check for entries for each day:
for ($day = 1; $day <= 31; $day++)
{
$d= sprintf('2009-12-%02d', $day);
if (isset($dates[$d])) {
// display the day number w/ a link
} else {
// display the day number
}
}
For your purposes a better SQL statement would be one that grabs the start date and the number of events on each day. This statement will only work properly if the start column is date column with no time component:
$sql= "SELECT start, end, COUNT(*) events_count FROM events WHERE start >= '2009-12-01' AND end <= '2009-12-31' GROUP BY start, end";

Categories