简体   繁体   中英

How to fetch previous month's data from database in php?

I am developing a php website and need to fetch some data from previous month. Not only first previous month but last five months data. And I am confused that how can I do this? In my database I've created two columns. One is "Month" and another is "Year". So row will look like


id ---- text ---- month ---- year

1 ---- hello ---- May ----- 2014

2 ---- hi ---- May ----- 2014


Now I can fetch data by using date() function like this.

$first_month = date('F', strtotime('-1 month'));
$second_month = date('F', strtotime('-2 month'));
$third_month = date('F', strtotime('-3 month'));

for five months, I can create five variables. But for year? I mean if current month is january and year 2014, then I will need to fetch data from December 2013, so how it will work? Can anyone suggest me?

I am so confused. Please tell me if anyone has done something like this before. I need idea or concept.

You could either restructure your tables to use a Unix timestamp or MySQL date , and select using comparator's. Or you could create temporary tables and do the same.

The direction you are heading will be nontrivial to maintain and debug. Also, the correct queries will be more complex than I believe you expect them to be. For instance, spanning years will be one line with the above. While many many lines going the way you are.

Edit: To maintain your current logic, the SQL Select statement would have to be a series of WHERE s. For instance:

SELECT * FROM table
WHERE
    (month IN ('April', 'May') AND year = 2014)

Would select the months of April and May in the year 2014.

The following would span a year:

SELECT * FROM table
WHERE
    (month IN ('December') AND year = 2013)
OR
    (month IN ('January') AND year = 2014)

From a programmatic standpoint, you would need to generate an array of years and months, including all months of the year you would like to select from.

The structure for such an array would look like such:

// For the first example
$where1 = array(
    2014 => array(
        'April',
        'May'
    )
);

// For the second example
$where2 = array(
    2013 => array(
        'December'
    ),
    2014 => array(
        'January'
    )
);

And you would have to create a WHERE clause from those arrays. Such as:

/**
 * Outputs
 * [where1] (month IN ('April', 'May') AND year = 2014)
 *
 * [where2] (month IN ('December') AND year = 2013) OR (month IN ('January') AND year = 2014)
 */
foreach(array('where1','where1') as $where_name) {

    $clause = '';

    $where = $$where_name;

    $wheres = array();

    foreach($where as $year => $months) {
        $wheres[] = "month IN ('" . implode("', '", $months) . "') AND year = $year";
    }

    $clause = '('.implode (') OR (', $wheres).')';

    echo "[$where_name] $clause\n\n";
}

That should do the trick. There is a working example here . Gathering the list of months is almost the same as you have been doing, but moreso like so:

    list($month, $year) = explode(" ", date('F Y', strtotime('-3 month')));

var_dump($month); // February
var_dump($year); // 2014

$array[$year][] = $month; // Will create the array structure as above

There are more efficient ways, but this is the general idea. I believe I have left you with some interesting tools to solve your problem.

To make this hit a range you would need to do something along the lines of:

$where3 = array();

for ($prev_months = 1; $prev_months <= 5; $prev_months++) {
    list($month, $year) = explode(" ", date('F Y', strtotime("-$prev_months month")));
    $where3[$year][] = $month;
}

You can view the working example here: http://ideone.com/UWI5wI

For reference, here are the examples of using your methodology vs the accepted norm:

// your last and 5
(month IN ('April', 'March', 'February', 'January') AND year = 2014) OR (month IN ('December') AND year = 2013)

// native 1 and 5
date <= 2014-05-01 01:00:00 AND date > 2013-12-01 01:00:00

I used the first (which is not convention) because every month has a first. You would want to use the last day of the target month, instead of the first day of the following month, but you get that.

The difference is much more apparent when spanning LONG periods of time:

// 2 years, yours
(month IN ('April', 'March', 'February', 'January') AND year = 2014) OR (month IN ('December', 'November', 'October', 'September', 'August', 'July', 'June', 'May', 'April', 'March', 'February', 'January') AND year = 2013) OR (month IN ('December', 'November', 'October', 'September', 'August', 'July', 'June', 'May') AND year = 2012)

// The conventional way is still just two comparators...

the MySQL date format is YYYY-MM-DD HH:MM:SS

or (to get the date format for one month ago):

date("Y-m-d H:i:s",strtotime("-1 month"));

You should be issuing a created (timestamp/datetime) column on new data, and simply searching through this data.

By creating month, day, year columns and trying to separate it you have only made this harder on yourself.

If you want to keep your table structure you can use what you have as this:

$month = date('F', strtotime('-6 month'));
$year = date('Y', strtotime('-6 month'));

Will get you November and 2013

Not sure what type of data you are storing but another option may be to name your tables based on the year and then have columns for each month

table name: year_2014

 id----m1---m2---m3 etc...
 1----hello
 2----hi
 3----Hey

Then your query would be:

$month = date("n", strtotime('-6 month'));
$year = date('Y', strtotime('-6 month'));
$monthval = "m" + $month;
$SQL = "SELECT " . $monthval . " FROM year_".$year;

SELECT m11 FROM year_2013

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM