Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 非常具体的MySQL查询,我想改进_Php_Mysql - Fatal编程技术网

Php 非常具体的MySQL查询,我想改进

Php 非常具体的MySQL查询,我想改进,php,mysql,Php,Mysql,这是我的场景:我有一个包含事件的表,每个事件都有一个名为“created”的字段,该字段带有创建该事件的时间戳。现在我需要对事件从最新到最旧进行排序,但我不希望MySQL将它们全部返回。我只需要给定时间间隔内的最新数据,例如24小时范围内的数据(编辑:我希望有一个灵活的解决方案,不仅是24小时范围内的,而且可能每隔几个小时)。我只需要最后10天。我已经做到了这一点,但我相信这是最低效的方式,也就是说: $timestamp = time(); for($i = 0; $i < 10; $

这是我的场景:我有一个包含事件的表,每个事件都有一个名为“created”的字段,该字段带有创建该事件的时间戳。现在我需要对事件从最新到最旧进行排序,但我不希望MySQL将它们全部返回。我只需要给定时间间隔内的最新数据,例如24小时范围内的数据(编辑:我希望有一个灵活的解决方案,不仅是24小时范围内的,而且可能每隔几个小时)。我只需要最后10天。我已经做到了这一点,但我相信这是最低效的方式,也就是说:

$timestamp = time();

for($i = 0; $i < 10; $i++) {
    $query = "SELECT * FROM `eventos` WHERE ... AND `created` < '{$timestamp}' ORDER BY `created` DESC LIMIT 1";    
    $return = $database->query( $query );

    if($database->num( $return ) > 0) {
        $event = $database->fetch( $return );
        $events[] = $event;

        $timestamp = $timestamp - 86400;
    }
}
$timestamp=time();
对于($i=0;$i<10;$i++){
$query=“通过`created`DESC LIMIT 1`从`eventos`中选择*并`created`<'{$timestamp}'顺序”;
$return=$database->query($query);
如果($database->num($return)>0){
$event=$database->fetch($return);
$events[]=$event;
$timestamp=$timestamp-86400;
}
}
我希望我说得够清楚了。谢谢
Jesús.

您希望在10天内完成所有活动,还是在10天内每天只完成一个活动


无论哪种方式,考虑寻求帮助。它应该可以帮助您获得所需的日期范围。

我会添加另一列,即日期(而不是时间),然后使用MySQL“group by”获取每个日期的最新值


本教程就是这样做的,但按产品类型而不是按日期。这应该有帮助

假设您希望在过去10天内每天发生最新(创建日期最大)的事件

因此,让我们每天获取最新的时间戳

$today = date('Y-m-d');
$tenDaysAgo = date('Y-m-d', strtotime('-10 day'));

$innerSql = "SELECT date_format(created, '%Y-%m-%d') day, MAX(created) max_created FROM eventos WHERE date_format(created, '%Y-%m-%d') BETWEEN '$today' and '$tenDaysAgo' GROUP BY date_format(created, '%Y-%m-%d')";
然后,我们可以选择与这些创建日期匹配的所有事件

$outerSql = "SELECT * FROM eventos INNER JOIN ($innerSql) as A WHERE eventos.created = A.max_created";
我还没有机会测试这一点,但原则应该足够合理

如果要按其他任意小时数分组,请更改innerSql:

$fromDate = '2012-07-06' // or if you want a specific time '2012-07-06 12:00:00'
$intervalInHours = 5;
$numberOfIntervals = 10;

$innerSql = "SELECT FLOOR(TIMESTAMPDIFF(HOUR, created, '$fromDate') / $intervalInHours) as grouping, MAX(created) as max_created FROM eventos WHERE created BETWEEN DATE_SUB('$fromDate', INTERVAL ($intervalInHours * $numberOfIntervals) HOUR) AND '$fromDate' GROUP BY FLOOR(TIMESTAMPDIFF(HOUR, created, '$fromDate') / $intervalInHours)";

如果您有一个以
created
作为前导列的索引,MySQL可能能够进行反向扫描。如果24小时内没有任何事件,则返回的行可能不是该时间段中的行。为了确保在该期间获得一行,您还需要在
created
列中包含一个下限,如下所示:

SELECT * FROM `eventos`
 WHERE ... 
   AND `created` <  FROM_UNIXTIME( {$timestamp} )
   AND `created` >= DATE_ADD(FROM_UNIXTIME( {$timestamp} ),INTERVAL -24 HOUR)
 ORDER BY `created` DESC
 LIMIT 1
从您的代码来看,24小时周期似乎是在任意时间限制的。。。如果time函数返回1341580800('2012-07-06 13:20'),则您的十个时段都是从给定日期的13:20到次日的13:20

(注意:如果您的参数是unix时间戳整数,请确保数据库对其进行了正确解释。)

在一个查询中提取十行可能更有效。如果可以保证“timestamp”是唯一的,那么就可以创建这样一个查询,但是查询文本将比现在复杂得多。我们可以在每个时段内获取MAX(timestamp_u2;),然后将其加入到行中。。。但那将是非常混乱的

如果我想把所有的十行都拉出来,我可能会尝试使用
UNION-all
的方法,虽然不是很漂亮,但至少可以调整一下

SELECT p0.*
  FROM ( SELECT * FROM `eventos` WHERE ... 
            AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL  0*24 HOUR)
            AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
          ORDER BY `created` DESC LIMIT 1
       ) p0 
 UNION ALL           
SELECT p1.*
  FROM ( SELECT * FROM `eventos` WHERE ... 
            AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
            AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
          ORDER BY `created` DESC LIMIT 1
       ) p1 
 UNION ALL           
SELECT p2.*
  FROM ( SELECT * FROM `eventos` WHERE ... 
            AND `created` <  DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
            AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -3*24 HOUR)
          ORDER BY `created` DESC LIMIT 1
       ) p2 
 UNION ALL           
SELECT p3.*
  FROM ...
然后把它放到你的桌子上

  ON `created` < p.period_end
 AND `created` >= DATE_ADD(p.period_end,INTERVAL -1 * {$nsecs} SECOND)
“创建”时的
=DATE\u ADD(p.period\u end,INTERVAL-1*{$nsecs}秒)
通过p.period\u end将每个时段组的最大值(已创建)向后拉,并将其包装在内联视图中

然后将其连接回您的表以获得每一行

但这真的非常混乱,很难理解,而且不可能比你已经在做的事情更快(或更高效)。您可以做的最大改进是运行9个查询所需的时间

试试这个:

    SELECT *
      FROM eventos
     WHERE created BETWEEN DATE_SUB(DATE(NOW()), INTERVAL 10 DAY) AND DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
  ORDER BY created DESC
     LIMIT 10

这里有一个将为您带来过去10天中每天的第一件事

  SELECT *
    FROM eventos
   WHERE created BETWEEN DATE_SUB(DATE(NOW()), INTERVAL 10 DAY) AND DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
GROUP BY DATE(created)
ORDER BY MAX(created) DESC
   LIMIT 10

我只想要10天内每天最新的答案。如果10天内每天最新的答案真的是你想要的,我相信我的第二个答案是迄今为止所有答案中最正确的。非常感谢你的回复,这是解决问题的好办法,但是如果我想要每5小时最新的答案呢?我需要一个更灵活的解决方案来改变时间间隔,我说每天都要简化,但还是要谢谢你D这个解决方案对我来说似乎很完美,但是如果时间戳间隔是5小时而不是每天,我应该做什么改变呢?我说每天一次来简化,谢谢你的时间!天数更容易,因为它们是数据中自然出现的组。你必须根据你的时间间隔创建一些人工组。你可以用你的时间间隔的模数来创建它。我已经更新了我的回复,使用的不仅仅是设定的天数。这是基于$fromDate值的小时间隔。注意:为了避免在一段时间内返回多行,您需要保证
timestamp
列的唯一性。我刚刚意识到这是错误的。你想要过去十天里每天最新的活动。这将给你最近的10个事件,最多10天。或者也许这没有错。我不太确定你在问什么。无论如何,我补充了另一个答案。希望这两个选项中的一个是您所追求的。以下是决定一天间隔的
按日期分组(创建)
DATE(created)
只是
created
的日期部分,没有时间。因此,如果您从每天(
DATE(created)
)获得最新的事件(
MAX(created)
),这将为您提供您想要的。如果你想要一天以外的时间间隔,我相信你必须以某种方式分组,而不是
DATE(created)
。例如,如果你想得到每小时而不是每天的第一篇帖子,你可以按CONCAT(DATE(created),'',hour(created))分组。基本上,我们的想法是将创建的
,四舍五入到最接近的值,然后按该值分组
    SELECT *
      FROM eventos
     WHERE created BETWEEN DATE_SUB(DATE(NOW()), INTERVAL 10 DAY) AND DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
  ORDER BY created DESC
     LIMIT 10
  SELECT *
    FROM eventos
   WHERE created BETWEEN DATE_SUB(DATE(NOW()), INTERVAL 10 DAY) AND DATE_ADD(DATE(NOW()), INTERVAL 1 DAY)
GROUP BY DATE(created)
ORDER BY MAX(created) DESC
   LIMIT 10