学说 - 得到下一个和上一个记录

时间:2015-02-23 09:44:09

标签: mysql symfony doctrine next

这样我就已经获得了一些记录。我有日期字段'已创建'现在我希望按日期获得下一个和上一个记录。

得到它的工作:

    $qb = $this->createQueryBuilder('a');

    $next = $qb->expr()->gt('a.created', ':date');
    $prev = $qb->expr()->lt('a.created', ':date');

    $prev = $qb->select('partial a.{id,title,created}')
        ->where($prev)
        ->setParameter('date', $date)
        ->orderBy('a.created', 'DESC')
        ->setMaxResults(1)
        ->getQuery()
        ->getArrayResult();

    $next = $qb->select('partial a.{id,title,created}')
        ->where($next)
        ->setParameter('date', $date)
        ->orderBy('a.created', 'DESC')
        ->setMaxResults(1)
        ->getQuery()
        ->getArrayResult();
它工作得很好。但这是数据库的2个问题。我需要一个。我可以通过加入等来做到这一点,但是当没有下一个或没有上一个时,我只得到一个空数组。

任何想法?

3 个答案:

答案 0 :(得分:6)

亚历山大的回应很接近。当您查询id < 2 LIMIT 1时,它会返回1,但如果您查询id < 5 LIMIT 1,这也会返回1。这是因为它返回1, 2, 3, 4并获取第一个元素,即1而不是所需的4

只需添加ORDER BY id DESC即可获取上一项。这将返回4, 3, 2, 1LIMIT 1将返回4或前一个元素。

$query = $em->createNativeQuery('SELECT id FROM users WHERE
        id = (SELECT id FROM users WHERE id > 2 LIMIT 1)
        OR
        id = (SELECT id FROM users WHERE id < 2 ORDER BY id DESC LIMIT 1)', $rsm);

答案 1 :(得分:3)

使用ORM实体存储库时本机SQL的替代方法。

namespace EntityNamespace;

use Doctrine\ORM\EntityRepository;

class MyEntityRepository extends EntityRepository
{

    /**
     * @param int $id
     * @return array|int[]
     */
    public function filterNextPrevious($id)
    {
        $expr = $this->_em->getExpressionBuilder();
        $qbNext = $this->createQueryBuilder('a')
           ->select(['MIN(a.id)'])
           ->where($expr->gt('a.id', ':id'));
        $qbPrevious = $this->createQueryBuilder('b')
            ->select(['MAX(b.id)'])
            ->where($expr->lt('b.id', ':id'));
        $query = $this->createQueryBuilder('m')
            ->select(['m.id'])
            ->where($expr->orX(
                $expr->eq('m.id', '(' . $qbNext->getDQL() . ')'),
                $expr->eq('m.id', '(' . $qbPrevious->getDQL() . ')')
            ))
            ->setParameter('id', $id)
            ->addOrderBy('m.id', 'ASC')
            ->getQuery();
       //optionally enable caching
       //$query->useQueryCache(true)->useResultCache(true, 3600);    

        return $query->getScalarResult();
    }
}

产生的DQL:

SELECT m.id 
FROM EntityNamespace\Entity m 
WHERE m.id = (
    SELECT MIN(a.id) 
    FROM EntityNamespace\Entity a 
    WHERE a.id > :id
) 
OR m.id = (
    SELECT MAX(b.id) 
    FROM EntityNamespace\Entity b 
    WHERE b.id < :id
) 
ORDER BY m.id ASC

(可选择通过$this->_em->createQuery($DQL)使用

代替querybuilder)

生成的数据集:

array(2) {
  [0]=>
  array(1) {
    ["id"]=>
    string(4) "5869"
  }
  [1]=>
  array(1) {
    ["id"]=>
    string(4) "5871"
  }
}

使用WHERE IN()条件的另一种方法是使用SELECT子查询,并可选择将总COUNT()添加到基表。

这将允许您将结果值分配给关联的键并取消ORDER BY子句。

$expr = $this->_em->getExpressionBuilder();
$next = $this->createQueryBuilder('a')
    ->select($expr->min('a.id'))
    ->where($expr->gt('a.id', ':id'));
$previous = $this->createQueryBuilder('b')
    ->select($expr->max('b.id'))
    ->where($expr->lt('b.id', ':id'));
$query = $this->createQueryBuilder('o')
    ->select('COUNT(o.id) as total')
    ->addSelect('(' . $previous->getDQL() . ') as previous')
    ->addSelect('(' . $next->getDQL() . ') as next')
    ->setParameter('id', $id)
    ->getQuery();

/* optionally enable caching
 * $query->useQueryCache(true)->useResultCache(true, 3600);
 */

return $query->getSingleResult();

结果DQL:

SELECT 
    COUNT(o.id) as total, 
    (
     SELECT MAX(b.id) 
     FROM EntityNamespace\Entity b 
     WHERE b.id < :id
    ) as previous, 
    (
     SELECT MIN(a.id) 
     FROM EntityNamespace\Entity a 
     WHERE a.id > :id
    ) as next 
FROM EntityNamespace\Entity o

生成的数据集:

array(3) {
    ["total"]=>
    string(4) "63156"
    ["previous"]=>
    string(4) "5869"
    ["next"]=>
    string(4) "5871"
}

答案 2 :(得分:2)

您可以使用原生查询:

/** @var EntityManager $em */
$em = $this->getDoctrine()->getManager();
$rsm = new ResultSetMapping();
$rsm->addScalarResult('id', 'id');

$query = $em->createNativeQuery('SELECT id FROM users WHERE
        id = (SELECT id FROM users WHERE id > 2 LIMIT 1)
    OR
        id = (SELECT id FROM users WHERE id < 2 LIMIT 1)', $rsm);
$users = $query->execute();

$ users 变量中,您将拥有以下数组:

[
    ['id' => 1]
    ['id' => 3]
]

此处有更多详情http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html