简体   繁体   中英

PHP Mysql get stats for a date range

I am getting a count of scans in a database. The time field is a mysql timestamp (2011-10-20 14:15:12). I have a function that lets me set a timeframe like 30 days, 60 days etc... this was working for weeks. Then I just noticed it broke.

function getScans($timeframe = 0)
{
    if ($timeframe != 0) { 
        $query = 'SELECT COUNT( * ) 
            FROM stats 
            WHERE time <= curdate( )+1 
            AND time >= curdate( )-' . ($timeframe - 1);
    } else {
        $query = 'SELECT COUNT( * ) 
            FROM stats';
    }

    $result = mysql_query($query);
    $row = mysql_fetch_array($result);
    return $row[0];
}

I know you have all heard this before but this was completely working last week. I went back today and noticed that when the $timeframe is other than 0, it no longer works. Any help is appreciated.

The problem is this: curdate( )+1 yields 20111131 (to day 2011-11-30) not what I believe you expect, 2011-12-01 , the same is true for the later curdate() call. It's probably been working fine because earlier in the month the calls have resulted in correct dates and MySQL accepts the formatting, but now it fails to alert on "impossible" dates. Closing in on next month, things start acting up.

The query should be rewritten like:

SELECT
  COUNT(*)
FROM `stats`
WHERE `stats`.`time` <= DATE_ADD(NOW(), INTERVAL 1 DAY)
  AND `stats`.`time` >= DATE_SUB(NOW(), INTERVAL $timeframe DAY)

You could do something like this:

function getScans($timeframe = 0)
{
    if ($timeframe != 0) { 
        $query = 'SELECT COUNT( * ) 
            FROM stats 
            WHERE time <= DATE_ADD(NOW(), INTERVAL 1 DAY) 
            AND time >= DATE_SUB(NOW(), INTERVAL ' . ($timeframe - 1) . ' DAY)';
    } else {
        $query = 'SELECT COUNT( * ) 
            FROM stats';
    }

    $result = mysql_query($query);
    $row = mysql_fetch_array($result);
    return $row[0];
}

But it isn't the safest approach if $timeframe could be supplied by a user or the like. Rather, you should consider using something like:

$query = sprintf ('SELECT
  COUNT(*)
FROM `stats`
WHERE `stats`.`time` <= DATE_ADD(NOW(), INTERVAL 1 DAY)
  AND `stats`.`time` >= DATE_SUB(NOW(), INTERVAL %d DAY)',
mysql_real_escape_string ($timeframe, $connection_handle));

or, better yet, search SO for tips on sanitizing user input before adding it to an SQL statement.

下面的单引号不是必需的,它破坏了该功能的其余部分。

.$timeframe - 1';

the format of curdate and timeframe might not be what you expect so the calculation isn't working. write the query in your phpmyadmin or equivalent and work out if there are syntax errors first and wether the output is as you expect

echo out the values and see the differences in PHP. then use these in your query.

correct result?

hope this helps

Hm i would rather do "all the logic" with PHP and then just run a pretty basic MySql query. Example you can get a timestamp (Ymd H:i:s) for dates in a past easily with this:

$dayago = date("Y-m-d", mktime(0, 0, 0, date("m"),date("d")-1,date("Y")));
$weekago = date("Y-m-d", mktime(0, 0, 0, date("m"),date("d")-7,date("Y")));
$monthago = date("Y-m-d", mktime(0, 0, 0, date("m"),date("d")-30,date("Y")));

It is also the same with the future dates so examples:

$tomorrow = date("Y-m-d", mktime(0, 0, 0, date("m"),date("d")+1,date("Y")));

So i will do all the logic with PHP get 2 dates and then run a Mysql query. Something like:

$count = mysql_result(mysql_query("SELECT COUNT(*) as Num FROM stats WHERE date>='$weekago' AND date<='$tomorrow'"),0);

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