Mysql 条令-获取下一个和上一个记录

Mysql 条令-获取下一个和上一个记录,mysql,symfony,doctrine,next,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('par

只是为了让我有一些准备好的唱片。我已经创建了日期字段,现在我想按日期获取下一条和上一条记录

通过以下方式使其工作:

    $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();
它工作得很好。但这是数据库的两个问题。我需要一个。我可以通过join等方法来实现这一点,但当没有next或prev时,我得到的只是一个空数组


有什么想法吗?

您可以使用本机查询:

/** @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();

更多详情请参见这里

Alexandr的回复已接近尾声。当您查询id<2限制1时,它将返回1,但如果您查询id<5限制1,它也将返回1。这是因为它返回1、2、3、4并获取第一个元素,即1而不是所需的4

只需添加ORDER BY id DESC即可获得上一个项目。这将返回4、3、2、1,限制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);

当使用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
使用WHERE IN条件的另一种替代方法是使用SELECT子查询,并可选地向基表添加一个总计数

这将允许您将结果值分配给相关联的键,并删除ORDERBY子句

结果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(2) {
  [0]=>
  array(1) {
    ["id"]=>
    string(4) "5869"
  }
  [1]=>
  array(1) {
    ["id"]=>
    string(4) "5871"
  }
}
$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();
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"
}