【问题标题】:Doctrine : how to make a nested query with the query builder?教义:如何使用查询构建器进行嵌套查询?
【发布时间】:2021-01-22 22:25:36
【问题描述】:

晚上好

我仍然是 SQL 查询和 Doctrine 查询构建器的初级。 我的问题很简单,简单到我找了几个小时。

我在一个 symfony 4.4 LTS 项目中。 我有一个表格,代表电子商务网站上的订单。有4个字段:id、custommer_id、created_at、status

我想要什么:

过去 20 个状态为“新”且 ID 为后代的订单

如果我进行 SQL 查询


SELECT *
FROM order o
WHERE o.status = 'new'.
ORDER BY o.created_at DESC, o.id DESC
limit 20

这是一个失败,因为我没有按降序获得 id。我仍然无法理解为什么。

最后我在 SQL 中找到了这个解决方案:

   SELECT * 
        FROM 
        (
            SELECT * 
            FROM order o 
            WHERE o.status = 'new'. 
            ORDER by created_at DESC 
            LIMIT 20 
        ) table_order
        ORDER by id DESC

酷!我按 ID 降序获取最后 20 条命令。

现在我必须使用 Doctrine 的 createQueryBuilder 来完成。 我尝试了很多解决方案都没有成功。 你能帮我么? 提前谢谢你

【问题讨论】:

    标签: symfony doctrine-query


    【解决方案1】:

    假设您的 Entity 类的名称为 Order

    $orders = $entityManager
        ->createQueryBuilder()
        ->from(Order::class, 'o')
        ->select('o')
        ->where('o.status = :newStatus')
        ->setParameter('newStatus', 'new')
        ->orderBy('o.created_at', 'DESC')
        ->addOrderBy('o.id', 'DESC')    
        ->getQuery()
        ->setMaxResults(20)
        ->getResult();
    

    但使用 DQL 会更好:

    $orders = $entityManager
        ->createQuery('
            SELECT o 
            FROM App\Entity\Order o
            WHERE o.status = :newStatus
            ORDER BY 
                o.created_at DESC AND
                o.id DESC
        ')
        ->setParameters(['newStatus' => 'new'])
        ->setMaxResults(20)
        ->getResult();
    

    【讨论】:

      【解决方案2】:

      通过dateid 获取最后 20 个订单几乎相同...

      订单越晚,id越大。

      如果在10:32:17 下的订单的id 为59
      然后在此之后下订单,让我们说10:32:29
      显然会得到 id 60

      除非您收到的订单太多以至于它们在同一秒内发生,
      通过dateid 订购是一样的。

      只需通过id 订购即可:

      public function getLastNewOrders() {
          $qb=$this->_em->createQueryBuilder();
      
          $qb->select("order")
             ->from(Order::class, "order")
             ->andWhere($qb->expr()->eq("order.status", "new")
             ->orderBy("order.id", "DESC")
             ->setMaxResults(20);
      
          return $qb->getQuery()->getResult();
      }
      

      【讨论】:

      • @SamMomm 这有关系吗?他使用 ID,而不是 UUID。就其本身而言,解决方案很简单,而是按日期排序
      • 这是一个品味问题。恕我直言,正确的方法是检查 createdAt
      【解决方案3】:

      非常感谢您的明确回答。 我的帖子不够精确。 把它放在上下文中,这是在我第一份工作的技术测试的上下文中。

      我收到了一个带有固定装置的 symfo 项目。 当我运行固定装置时,我在“订单”表中得到非常不一致的数据。也就是说你在选择按ID排序还是created_At排序时你提出的Preciel的逻辑不能保留。 让我解释一下:

      查看 Order 表中的最后 9 个命令。查看 ID,它们的顺序非常不连贯。 这样做是为了让测试更复杂吗?我不知道。

      如果我使用 status= 'new' 减少表订单的最后 5 个订单,我会得到:

      我被要求按 ID 降序排序,所以我想得到这个:

      所以您提出的解决方案不按 ID 降序排列。

      炖牛肉: 你向我提出了这个建议:

      $orders = $entityManager
          ->createQueryBuilder()
          ->from(Order::class, 'o')
          ->select('o')
          ->where('o.status = :newStatus')
          ->setParameter('newStatus', 'new')
          ->orderBy('o.created_at', 'DESC')
          ->addOrderBy('o.id', 'DESC')    
          ->getQuery()
          ->setMaxResults(20)
          ->getResult(); 
      

      我明白了,所以不好。

      有这样的sql请求,就好了:

        SELECT * 
              FROM 
              (
                  SELECT * 
                  FROM order o 
                  WHERE o.status = 'new'. 
                  ORDER by created_at DESC 
                  LIMIT 20 
              ) table_order
              ORDER by id DESC
      

      但是我不能用 querybulder 来做。

      非常感谢您的宝贵时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-01
        • 2016-11-16
        • 2018-07-17
        • 1970-01-01
        • 1970-01-01
        • 2011-09-25
        • 1970-01-01
        相关资源
        最近更新 更多