我有一个订单表(订单),一个状态表(order_statuses)和一个透视表,该表旨在用作状态日志(order_order_status)。
更改订单状态后,会将条目添加到数据透视表中。数据透视表中该订单的最新条目将是其当前状态。
我需要能够显示当前具有给定状态的所有订单。例如,所有处于“报价”状态的订单。有没有一种雄辩的方式来构建此查询?
(编辑,附加说明:订单的当前状态是状态日志中具有最新“ created_at”日期的条目。)
以下是模式的一些示例:
mysql> SELECT * FROM orders WHERE id = 2;
+----+---------+--------------+---------------+----------------------+---------------------+---------------------+
| id | user_id | order_number | job_reference | accounting_reference | created_at | updated_at |
+----+---------+--------------+---------------+----------------------+---------------------+---------------------+
| 2 | 73 | 37-5 | Janis Joplin | NULL | 2018-06-25 02:27:21 | 2018-06-25 02:27:21 |
+----+---------+--------------+---------------+----------------------+---------------------+---------------------+
mysql> SELECT * FROM order_order_status WHERE order_id = 2 ORDER BY created_at;
+------+----------+-----------------+---------+---------------------+---------------------+
| id | order_id | order_status_id | user_id | created_at | updated_at |
+------+----------+-----------------+---------+---------------------+---------------------+
| 2 | 2 | 2 | 753 | 2012-06-27 09:47:00 | 2012-06-27 09:47:00 |
| 3 | 2 | 3 | 753 | 2012-06-27 09:56:00 | 2012-06-27 09:56:00 |
| 4 | 2 | 4 | 753 | 2012-06-27 09:56:00 | 2012-06-27 09:56:00 |
| 5 | 2 | 5 | 1153 | 2012-06-27 10:13:00 | 2012-06-27 10:13:00 |
| 6 | 2 | 6 | 1153 | 2012-06-27 10:13:00 | 2012-06-27 10:13:00 |
| 7 | 2 | 10 | 1153 | 2012-06-27 10:13:00 | 2012-06-27 10:13:00 |
| 8 | 2 | 7 | 1153 | 2012-06-27 10:13:00 | 2012-06-27 10:13:00 |
| 9 | 2 | 10 | 1153 | 2012-06-27 10:42:00 | 2012-06-27 10:42:00 |
| 10 | 2 | 7 | 1153 | 2012-06-27 10:42:00 | 2012-06-27 10:42:00 |
| 11 | 2 | 8 | 753 | 2012-06-27 10:44:00 | 2012-06-27 10:44:00 |
| 12 | 2 | 9 | 753 | 2012-06-27 10:45:00 | 2012-06-27 10:45:00 |
| 2222 | 2 | 10 | 54 | 2013-01-03 12:08:00 | 2013-01-03 12:08:00 |
+------+----------+-----------------+---------+---------------------+---------------------+
mysql> SELECT * FROM order_statuses;
+----+----------------+----------------+---------------------+---------------------+
| id | title | tag | created_at | updated_at |
+----+----------------+----------------+---------------------+---------------------+
| 1 | Archived Quote | archived_quote | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 2 | Quote | quote | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 3 | Order | order | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 4 | Confirmed | confirmed | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 5 | Manufacturing | manufacturing | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 6 | Painting | painting | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 7 | Dispatched | dispatched | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 8 | Invoiced | invoiced | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 9 | Paid | paid | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 10 | Closed | closed | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
| 11 | Archived | archived | 2018-06-25 02:25:28 | 2018-06-25 02:25:28 |
+----+----------------+----------------+---------------------+---------------------+
编辑:进一步澄清。这是返回所需结果的SQL查询。我正在寻找一种获得相同结果的雄辩方法:
SELECT a.order_status_id, c.*
FROM order_order_status a
INNER JOIN (
SELECT order_id, MAX(updated_at) last_date
FROM order_order_status
GROUP BY order_id
) b ON a.order_id = b.order_id AND a.updated_at = b.last_date
INNER JOIN
orders c
ON c.id = a.order_id
WHERE a.order_status_id = (SELECT id from order_statuses where tag="closed")
答案 0 :(得分:1)
您需要在每个模型中添加一些关系才能加入它们
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class orders extends Model
{
protected $table = 't_orders';
protected $primaryKey = 'id';
// join t_orders with t_order_order_status but get only the latest matching row out of order_order_status
public function status_log()
{
return $this->hasMany('App\Model\order_order_status', 'order_id','id')->orderBy('t_order_order_status.id', 'desc')->limit(1);
}
}
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class order_order_status extends Model
{
protected $table = 't_order_order_status';
protected $primaryKey = 'id';
// join t_orders with t_order_order_status
public function status_name()
{
return $this->hasOne('App\Model\order_statuses', 'id','order_status_id');
}
}
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class order_statuses extends Model
{
protected $table = 't_order_statuses';
protected $primaryKey = 'id';
}
然后您将执行以下操作
App\Model\orders::with('status_log.status_name')->get();
应该得到这样的东西
[
{
"id":2,
"user_id":73,
"order_number":"37-5",
"job_reference":"Janis Joplin",
"accounting_reference":null,
"created_at":"2018-06-25 02:27:21",
"updated_at":"2018-06-25 02:27:21",
"status_log":[{
"id":4,
"order_id":2,
"order_status_id":4,
"user_id":753,
"created_at":"2012-06-27 09:56:00",
"updated_at":"2012-06-27 09:56:00",
"status_name":{
"id":4,
"title":"Confirmed",
"tag":"confirmed",
"created_at":"2018-06-25 02:25:28",
"updated_at":"2018-06-25 02:25:28"
}
}]
}
]
请注意,为便于阅读,我为表名添加了t_
前缀,但您可以将其命名为与模型相同的名称。
更新
为此,您可以使用类似这样的方式来传递将根据状态ID进行过滤的clusre
$status = 3;
$result = App\Model\orders::with(['status_log'=>function($query) use($status) {
$query->where('t_order_order_status.order_status_id','=', $status);
$query->with('status_name');
}])->get();
return $result;
会给予
[{
"id":2,
"user_id":73,
"order_number":"37-5",
"job_reference":"Janis Joplin",
"accounting_reference":null,
"created_at":"2018-06-25 02:27:21",
"updated_at":"2018-06-25 02:27:21",
"status_log":[{ // will be empty [] for order not in t_order_order_status
"id":3,
"order_id":2,
"order_status_id":3,
"user_id":753,
"created_at":"2012-06-27 09:56:00",
"updated_at":"2012-06-27 09:56:00",
"status_name":{
"id":3,
"title":"Order",
"tag":"order",
"created_at":"2018-06-25 02:25:28",
"updated_at":"2018-06-25 02:25:28"
}
}]
}]
它将返回所有订单,但是您可以使用status_log
来找出它在t_order_order_status
表中是否有任何记录,但是如果您想删除“多余”并仅保留那些订单记录器表中有这些记录,那么您可以在$result
上使用过滤器。
return $result->filter(function ($item) {
return !empty($item->status_log && count($item->status_log));
});
答案 1 :(得分:1)
您必须使用Join。 Eloquent在获取多对多关系时创建两个查询。在这种情况下,不能雄辩地使用命令。
更新
查询生成器将是您最好的选择,不幸的是,已接受的答案效率极低,至少可以说扩展性不佳。在我头顶上的查询将是这样的:
$orders = DB::table('orders')
->leftJoin('order_order_status', 'orders.id', '=', 'order_order_status.order_id')
->leftJoin('order_statuses', function ($join) use ($title) {
$join->on(
'order_order_status.order_status_id',
'=',
DB::raw('SELECT id FROM order_statuses WHERE title = ' . $title . ' AND order_order_status.order_status_id = order_statuses.id ORDER BY created_at DESC LIMIT 1')
);
})
->select('orders.*')
->groupBy('orders.id')
->get();
答案 2 :(得分:0)
php artisan make:model用户
在您的用户模型中:
protected $table='users';
public $primaryKey='id';
public function orders(){
return $this->belongsToMany('App\Model\Orders','order_order_status','user_id','order_id')->orderby('created_at','desc');
}
php artisan make:model Order
在您的订单模型中:
protected $table='orders';
public $primaryKey='id';
public function user(){
return $this->belongsTo('App\Model\User','user_id');
}
public function order_status()
{
return $this->belongsToMany('App\Model\OrderStatus','order_order_status','order_id','order_status_id')->withTimestamps();
}
php artisan make:model OrderStatus
在您的OrderStatus模型中:
protected $table='order_statuses';
public $primaryKey='id';
public function orders()
{
return $this->belongsToMany('App\Model\Order','order_order_status')->with('user')->orderBy('created_at','desc');
}
php artisan make:controller OrdersController
现在,您要按OrderStatus title ='Quote'
来获取订单。在您的OrdersController中:
use Illuminate\Http\Request;
public function get_order(Request $request,$title){
// $title='Quote';
$orders=OrderStatus::where('title',$title)->with('orders')->get();
return response()->json($orders);
}