MySQL/PHP get average of past two months based on variable month - php

I'm trying to get an average of a value for the past 2 months, but not based on CURDATE()/NOW(). It would be dependent on what month the user was looking at in the application:
Ex:
If I'm looking at May, I would want the average of April and March.
If I'm looking at February, I would want the average of January and December (of the previous year).
I have a function that accepts the month and year of the page the user is on (it also accepts the emp_id, but that is irrelevant for this question).
public function getProtectedAmt($month,$year,$id){
$query = "SELECT avg(total_payout) as avg_payout FROM saved_plan_data WHERE emp_id = '$id' AND //this is where i dont know what to query for";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_assoc($result);
return $row['avg_payout'];
}
In the table saved_plan_data, there are fields plan_month and plan_year that store INT values of what month/year the employee's total_payout is saved for.
How do I write my WHERE clause to get the AVG for the previous 2 months, depending on what the values of $month and $year are?

I think the easier and more readable solution is this one:
SELECT ...
FROM ...
WHERE
(plan_year, plan_month) IN ((2012, 12), (2013, 1))
You just need to compute the appropriate values.
This is also quite readable:
WHERE CONCAT_WS('-', plan_year, plan_month) IN ('2012-12', '2013-01')

In the function, create two variables $q_month & $q_year.
Set these as comma separated past two months. E.g. if currently the date is May 22, 2013, set the values to $q_month = 4,3 and $q_year = 2013
Use these variables in your query as WHERE Month in ($q_month) and Year in ($q_year)

Edit: Mis-read the question. This would get you the average for the last two months combined.
You could either be very verbose saying where (month and year) or (month and year)
SELECT avg(total_payout) as avg_payout
FROM saved_plan_data
WHERE emp_id=$id
AND (
(plan_month = $month1 AND plan_year = $year1)
OR (plan_month = $month2 AND plan_year = $year2)
)
Or you can cast the plan_month and plan_year as a date and check if the value is between two dates:
SELECT avg(total_payout) as avg_payout
FROM saved_plan_data
WHERE emp_id=$id
AND STR_TO_DATE(CONCAT_WS('-',plan_year,plan_month,'1'),'%Y-%m-%d')
BETWEEN '$year1-$month1-1' AND '$year2-$month2-1'
Also, you really should just store the month and year together. Here is a SO question with good answers about it: mysql datatype to store month and year only

I think the easiest way is to think of the year/month combinations as a number of months since year/month 0. That is, convert to number of months by multiplying the year times 12 and adding the months.
Then the previous two months is easy, and you don't have to worry about year boundaries:
SELECT avg(total_payout) as avg_payout
FROM saved_plan_data
WHERE emp_id = '$id' AND
plan_year*12 + plan_month in ($year*12+month - 1, $year*12+month - 2)

Related

How to find all the data that match a particular month from mysql database?

I am currently having problem getting all the data from the database that match a particular month and show all the data from that month only. here's what I tried.
<?php
require('./connect.php');
?>
<?php
$name1 = $conn->prepare("SELECT * FROM garden WHERE MONTH(Apr)");
$name1->execute();
while($row = $name1->fetch()) {
$t = $row["temp"];
echo $t;
echo "sdasds";
}
?>
The database has time column that stores date as 12-Apr-2017 and I want to find all the details of april month or may month.
You're not using MONTH() correctly. You need to pass the column identifier as the parameter and compare its value to the value you want which is 4 as April is the fourth month:
SELECT * FROM garden WHERE MONTH(STR_TO_DATE(dateColumn, '%e-%b-%Y')) = 4
If you want a more readable query use MONTHNAME()
SELECT * FROM garden WHERE MONTHNAME(STR_TO_DATE(dateColumn, '%e-%b-%Y')) = 'April'
You will also notice I use STR_TO_DATE() as you stored your dates as strings instead of dates. In the future you should consider storing dates as date values as converting them into a different format is easy and it makes doing date work a lot easier.
Instead of providing Apr as parameter, pass 4 for april month. Then
Your query would look like
SELECT * FROM garden WHERE EXTRACT(MONTH FROM time) = 4;
Hope this helps :)

Select Mysql with multiple greater and lower values

i am in need of a search query based on 6 values from 3 columns day, month, year, right now i have got it some how working only for month and year but i can not get the day to perform correctly.
for example if some one wants to search from day, month year to day month year.
my current query
//From
list($fy,$fm,$fd) = explode ('-', 2013-2-20);
//to
list($ty,$tm,$td) = explode ('-', 2014-9-1);
$add = " AND
( month >= '".$fm."'
AND year >='".$fy."') AND (
month <= '".$tm."'
AND year <= '".$ty."'
) ";
as you can see the day is not included, your time is much appreciated.
Going on with what you have. You would just add day in the same way you added month and year:
...
$add = " AND
( month >= '".$fm."'
AND year >='".$fy."'
AND day >='".$fd."') AND (
month <= '".$tm."'
AND year <= '".$ty."'
AND day <= '".$td."'
) ";
...
Since all the items are independent of each other, this works of the literal values are higher/lower in each item. Which is probably not what you want. You will need to convert the strings '2013-2-20' into DATE and then use those. This can be done with str_to_date(). So for example str_to_date('2013-2-20','%Y-%m-%d').
Notice: I'm aware that you cannot change the database but for future references it's a good idea to have a single DATE datatype for your database. It's not good design to separate them into separates things such as day, month, and year. As with using the DATE datatype it can easily find lower and higher dates by simply comparing the dates (along with date functions using dates can be used):
dateObj1 >= dateObj2 // dateObj1 is at a later date than dateObj2

DateTime: Converting 'yW' to earliest and latest possible dates, then BACK TO 'yW'?

The Issue:
We have some products which use a "YYWW" (date('yW')) format to identify date of creation.
Sometimes we don't even get the week .. all we have to work with is the year value.
I am currently using DateTime->setISODate() to get dates out of the year and week values.
Since the turn of a new year usually falls in the middle of a calendar week, our minimum-date is typically in the prior year when considering week-One.
This isn't much of a problem in and of itself, bet when trying to convert back to the original date code string, I'm getting the wrong year value.
Goal:
Our goal is to
store a given YYWW value to the DB as two values, their earliest and latest possible Dates.
then, from those min/max dates, accurately rebuild the original year/week string when needed for views.
Examples: 'Code' to 'date': OK
Code "09" becomes min 2008-12-29 / max 2009-12-27
Code "0901" becomes min 2008-12-29 / max 2009-01-04
Code "0922" becomes min 2009-05-25 / max 2009-05-31
Examples: 'date' to 'Code': FAILED
Date 2009-12-27 = "0952" ... success
Date 2009-05-31 = "0922" ... success
Date 2009-05-25 = "0922" ... success
Date 2009-01-04 = "0901" ... success
Date 2008-12-29 = "0801" ... FAIL: expected "0901"
Tried:
### Simplified for brevity ###
$dateOfMfg = '0901';
$dc = aCustomValidatorAndStuff($dateOfMfg); // returns array('year' => 2009, 'week' => 1)
$dateTimeMin = new DateTime();
$dateTimeMax = new DateTime();
$result = array(
'min' => $dateTimeMin->setISODate($dc['year'], $dc['week'], 1),
'max' => $dateTimeMax->setISODate($dc['year'], $dc['week'], 7),
);
echo '<pre>Result:<br />',var_dump($result),'</pre>';
echo 'Min: ',$result['min']->format('yW'),'<br />'; // "0801" ... Bad
echo 'Min: ',$result['max']->format('yW'),'<br />'; // "0901" ... Good
Summary:
Is there a native way to get the appropriate year value for that "min" year?
What other suggestions come to mind?
I think storing a calendar table in the database makes the most sense here. A calendar table can greatly simplify your code. Queries written against a calendar table are often obviously correct. There's a lot of value in that.
One way to answer your failed question with a calendar table is to return the full set of dates.
select cal_date
from calendar
where iso_year = (select iso_year from calendar where cal_date = '2008-12-29')
and iso_week = (select iso_week from calendar where cal_date = '2008-12-29')
order by cal_date;
cal_date
--
2008-12-29
2008-12-30
2008-12-31
2009-01-01
2009-01-02
2009-01-03
2009-01-04
I think that statement is easier to understand, but a JOIN often performs better.
select c2.cal_date
from calendar c1
inner join calendar c2
on c1.iso_year = c2.iso_year
and c1.iso_week = c2.iso_week
where c1.cal_date ='2008-12-29'
order by c2.cal_date;
Something to think about
Code "09" becomes min 2008-12-29 / max 2009-12-27
The ISO year 2009 starts on 2008-12-29, but it doesn't end on 2009-12-27. It ends on 2010-01-03;

Using PHP to select table entries using two date fields and current month

Please help a newbee. I have a table named event_calendar with fields named ec_start_date, ec_end_date and ec_event_name. The first two fields are date fields. It is a small table, with less than 100 entries. I want to list events with a start or end date in the current month, then I want to follow with a list of events with a start or end date in the next month. The two list will be headed by the month name. I would like the dates displayed in the list to be in the format dd/mm.
This is the code I've found to identify the months for the list headers.
$thismonth = mktime(0,0,0,date("n"));
$nextmonth = mktime(0,0,0,date("n")+1);
echo "<h2 class='caps'>";
echo date("n", $thismonth);
echo "</h2>";
echo "<h2 class='caps'>";
echo date("m", $nextmonth);
echo "</h2>";
This is the code I use to pull the entries for this month's (August) activities
$query = "SELECT ec_display,ec_event_name,ec_start_date,ec_end_date FROM event_calendar WHERE month(ec_start_date) = 8 OR month(ec_end_date) = 8 ORDER BY ec_start_date";
The problem is, if I replace the number 8 with the variable $thismonth, it fails.
Finally, how can I display only the dd/mm from ec_start_date and ec_end_date?
I greatly appreciate any guidance, but please be specific as I am very new to this! Thank you!
$thismonth contains a UNIX timestamp returned by mktime. The timestamp for hour 0, minute 0, second 0 of month 8 of this year is 1312862400. That's not 8.
Don't put that in your query, put date('n') (8) in it... or just let MySQL do it
$query = "SELECT ec_display,ec_event_name,ec_start_date,ec_end_date FROM event_calendar WHERE month(ec_start_date) = MONTH(CURRENT_DATE) OR month(ec_end_date) = MONTH(CURRENT_DATE) ORDER BY ec_start_date";

How many weeks are inside of two dates

I have starting dates and ending dates in my database (MySQL).
How can I get the answer, how many weeks(or days) are inside of those 2 dates? (mysql or php)
For example I have this kind of database:
Started and | will_end
2009-12-17 | 2009-12-24
2009-12-12 | 2009-12-26
...
Update to the question:
How to use DATEDIFF?
How can I make this to work? or should I use DATEDIFF completly differently?
SELECT DATEDIFF('Started ','will_end') AS 'Duration' FROM my_table WHERE id = '110';
If the two columns $d1 and $d2 store unix timestamp obtained from time() then this simple line suffices:
$diffweek = abs($d1 - $d2) / 604800;
Otherwise if the columns are of DATETIME type, then:
$diffweek = abs(strtotime($d1) - strtotime($d2)) / 604800;
p/s: 604800 is the number of seconds in a week (60 * 60 * 24 * 7)
p/s2: you might want to intval($diffweek) or round($diffweek)
Calculating the number of days and dividing by seven won't give you the number of weeks between the two dates. Instead it will return the result of division by 7 that doesn't always correspond to the number of weeks between the two dates when thinking in terms of the number of weeks in the ISO calculation.
For example, given start_date = "2010-12-26" and end_date = "2011-01-25" you will be going through W51,52,01,02,03,04 and those are 6 weeks as per ISO, but if you simply calculate the difference and divide by 7, you'll get 5.
The issue appears when the start date and end date belong to different years.
The best way to do the calculation is to get the last week number of the start_date year and it should refer to the December, 28.
function weeks($ladate2,$ladate3) {
$start_week= date("W",strtotime($ladate2));
$end_week= date("W",strtotime($ladate3));
$number_of_weeks= $end_week - $start_week;
$weeks=array();
$weeks[]=$start_week;
$increment_date=$ladate2;
$i="1";
if ($number_of_weeks<0){
$start_year=date("Y",strtotime($ladate2));
$last_week_of_year= date("W",strtotime("$start_year-12-28"));
$number_of_weeks=($last_week_of_year-$start_week)+$end_week;
}
while ($i<=$number_of_weeks)
{
$increment_date=date("Y-m-d", strtotime($ladate2. " +$i week"));
$weeks[]=date("W",strtotime($increment_date));
$i=$i+1;
}
return $weeks;
}
function diff_weeks($ladate2,$ladate3) {
$weeks=weeks($ladate2,$ladate3);
$diff_weeks=count($weeks);
return $diff_weeks;
}
Best regards,
Manikam
MySQL has datediff which returns the difference in days between two dates, since MySQL 4.1.1.
Do note that, as per the manual, DATEDIFF(expr1,expr2) returns expr1 – expr2 expressed as a value in days from one date to the other. expr1 and expr2 are date or date-and-time expressions. Only the date parts of the values are used in the calculation.
You can use the TO_DAYS function on each date and subtract the two to calculate the difference in days.
DATEDIFF
Find the days and divide by 7
<?php
$dayDif = date('z',strtotime('2009-12-17)') - date('z',strtotime('2009-12-24)');
$numWeeks = $dayDif / 7;
?>
The z option for php's date function gives you the day of the year (0 - 365). By subtracting the two values you find how many days between dates. Then factor by seven for the number of weeks.
Read this page closely, the date() function is rich. http://php.net/manual/en/function.date.php

Categories