【问题标题】:Laravel 5.1 get Orders that have been completedLaravel 5.1 获取已完成的订单
【发布时间】:2017-09-05 18:06:20
【问题描述】:

我有一个Order 模型和一个OrderStatus 模型。一个Order 可以有多个状态,但只有一个“当前状态”(这由数据透视表order_status 上的created_at 时间戳定义)。

Order 模型(orders 表)

OrderStatus 模型(order_statuses 表)

order_status 数据透视表(order_status 表)

如何定义查询范围(或类似范围)以获取某个状态的所有Orders;即“完成”?

以下不起作用,因为它会检查订单的所有状态,甚至是过去的状态。

public function scopeCompleted($query)
{
    return $query->whereHas('statuses', function($q) {
        return $q->where('statuses.id', 10);
    });
}

生成的SQL是:

select  *
    from  `orders`
    where  `orders`.`deleted_at` is null
      and (
        SELECT  count(*)
            from  `statuses`
            inner join  `order_status`  ON `statuses`.`id` = `order_status`.`status_id`
            where  `status`.`id` = `orders`.`id`
              and  `statuses`.`id` = ?
          ) >= 1 

这会错误地返回所有 状态 ID 为 10 的订单,而不是只返回 当前 状态 ID 为 10 的订单。

order_status 数据透视表

+----+----------+-----------------+-------------+---------------------+
| id | order_id | order_status_id | approver_id | approved_at         |
+----+----------+-----------------+-------------+---------------------+
| 11 | 2        | 9               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 10 | 2        | 10              | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 9  | 2        | 5               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 8  | 2        | 2               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 7  | 2        | 1               | NULL        | 2017-04-10 13:33:25 |
+----+----------+-----------------+-------------+---------------------+
| 6  | 1        | 10              | NULL        | 2017-04-10 13:32:09 |
+----+----------+-----------------+-------------+---------------------+
| 5  | 1        | 9               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 4  | 1        | 7               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 3  | 1        | 5               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 2  | 1        | 2               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+
| 1  | 1        | 1               | NULL        | 2017-04-10 13:32:05 |
+----+----------+-----------------+-------------+---------------------+

例如,上面的order_status 数据透视表显示了两个具有多个状态条目的订单。由此,当请求已完成的订单(状态 10)时,只应返回一个订单(ID 为 1 的订单),因为订单 2 不再完成,它已被更新为另一种状态。

【问题讨论】:

  • 请给我们看一下生成的SQL。
  • @RickJames 我已经更新了我的问题以包含 SQL。谢谢
  • 如果您在订单表中保留current_status_id 字段并相应地更新它,这会容易得多。

标签: php mysql eloquent laravel-5.1 pivot-table


【解决方案1】:

首先,这样会更好:

select  *
    from  `orders`
    where  `orders`.`deleted_at` is null
      and EXISTS (
        SELECT  *
            from  `statuses`
            inner join  `order_status`
                ON `statuses`.`id` = `order_status`.`status_id`
            where  `status`.`id` = `orders`.`id`
              and  `statuses`.`id` = ?
                 );

你并不需要完整的计数,你只需要知道是否存在。

但是查询是不可能的,因为没有提到status表!

一旦你解决了这个问题,我们就可以讨论如何避免子查询。

【讨论】:

  • OrderStatus 表存储所有可能的状态,order_status 数据透视表保持两者之间的关系。我之前设法用子查询解决了它并且它正在工作,但是你暗示使用子查询是不好的,不是吗?如果是这样,我将如何以不同的方式处理它?
  • 子查询通常很慢。也许您的桌子还不够大,无法看到这种呆滞状态。
  • 如果不使用子查询,您建议如何获取已完成的订单?
  • 您需要groupwise max 才能仅获取“当前”行。
猜你喜欢
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多