从数据库获取日期或第一个较低的日期

时间:2017-08-31 11:25:38

标签: php mysql symfony select

如何找到第一个低于数据库的日期。 如果这个日期不存在,我需要在数据库中查找日期 - 比今天日期晚30天。我需要比第一个更低的日期。

    2017-08-30
    2017-08-23
    2017-08-16
    2017-08-09
    2017-08-02
    2017-07-26
    2017-07-19

例如,我今天的数据是

  

2017年8月30日

所以我需要在2017-08-30之间找到日期-30天

  

(将于2017年7月31日)

如果数据库中不存在此数据,我需要采用第一个低于31.07.2017的日期

  

所以这个日期将是2017-07-26

我试过了:

$lastMonth = date_format(new \Datetime('-30 days'), 'Y-m-d');
    for($i= 0; $i<7;){
            $parts = explode('-', $lastMonth);
            $lastMonth = date('Y-m-d', mktime(0, 0, 0, $parts[1], $parts[2] - $i, $parts[0]));
            $query = $this->em->createQuery(

                'SELECT sum(psc.score) / COUNT(psc.id) as avgscore, psc.date
    FROM AppBundle:PageSpeedScore psc
    WHERE psc.projectId = :projectId
    AND psc.date = :date
    GROUP BY psc.date, psc.projectId
    ORDER BY psc.date
    '
            )->setParameter('projectId', $projectId)
            ->setParameter('date', $lastMonth);
        if(empty($query->getResult())){
            $i++;
        }else{
            $date = $query->getResult();
            break;
        }
        }

这让我回到2017-07-26所以它的工作但是......我认为这不是优雅的方式。 我现在对数据库有很多疑问。我想我可以用一个查询来做到这一点。也许有人可以帮助我并告诉我如何在没有for循环的情况下只在mySQL查询中执行此操作?

2 个答案:

答案 0 :(得分:1)

如果我理解正确的话,这段代码应该可以解决问题:

$query = $this->em->createQuery(
        'SELECT sum(psc.score) / COUNT(psc.id) as avgscore, psc.date
        FROM AppBundle:PageSpeedScore psc
        WHERE psc.projectId = :projectId
        AND psc.date <= :date AND DATE_ADD(psc.date, 7, 'DAY') >= :date
        GROUP BY psc.date, psc.projectId
        ORDER BY psc.date DESC')
    ->setParameter('projectId', $projectId)
    ->setParameter('date', $lastMonth)
    ->setMaxResults(1)
    ->getSingleResult();

您基本上搜索的是等于阈值日期(psc.date <= :date)且日期少于您的起点日期(DATE_ADD(psc.date, 7, 'DAY') >= :date)的日期的效果结果。

您按日期按降序排列结果(ORDER BY psc.date DESC),因此阈值以下的最新日期是结果集中的第一条记录。

然后,您调用->setMaxResults(1)仅检索此第一条记录并将其与->getSingleResult()一起返回。如果找不到匹配的结果,getSingleResult将抛出一个NoResultException,你可以捕获它,然后使用你的默认值。

答案 1 :(得分:0)

删除整个循环并改为执行此操作

SELECT sum(psc.score) / COUNT(psc.id) as avgscore, MAX(psc.date) AS thedate
FROM AppBundle:PageSpeedScore psc
WHERE psc.projectId = :projectId
AND psc.date <= (SELECT DATE_SUB(MAX(`date`), INTERVAL 30 DAY) 
                     FROM AppBundle:PageSpeedScore 
                     WHERE projectId = :projectId
                    )

您只需要一个查询并绑定您的项目

由于SELECT子句的所有列都有一个聚合函数,因此不需要GROUP BY