(Laravel) Как отфильтровать таблицу по новейшему значению пивота - PullRequest
0 голосов
/ 25 июня 2018

У меня есть таблица заказов (ордеров), таблица статусов (order_statuses) и сводная таблица, которая должна быть журналом состояния (order_order_status).

Когда статус заказа изменяется,запись добавлена ​​в сводную таблицу.Последней записью в сводной таблице для этого ордера будет его текущий статус.

Мне нужно иметь возможность отображать все ордера, которые в настоящее время имеют данный статус.Например, все заказы в статусе «Цитировать».Существует ли красноречивый способ создания этого запроса?

(РЕДАКТИРОВАТЬ, дополнительные пояснения: статус ТЕКУЩЕГО ордера - это запись в журнале состояния с самой новой датой «create_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 |
+----+----------------+----------------+---------------------+---------------------+

EDIT: дополнительные пояснения.Это 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")

Ответы [ 3 ]

0 голосов
/ 25 июня 2018

Вам необходимо добавить некоторые отношения в каждую модель, чтобы присоединиться к ним

orders

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);
    }

}

order_order_status

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');
    }

}

order_statuses

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_, но вы можете назватьони такие же, как ваши модели.

ОБНОВЛЕНИЕ

Для этого вы можете использовать что-то вроде этого, передавая кластер, который будет фильтровать на основе идентификатора статуса

$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));
});
0 голосов
/ 25 июня 2018

Вы должны использовать Регистрация . Eloquent создает два запроса при извлечении множества отношений. К сожалению, в этом случае нельзя использовать заказ с помощью 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();
0 голосов
/ 25 июня 2018

php artisan make: модель User

в вашей пользовательской модели:

   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: модель 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: модель 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'

в вашем контроллере Orders:

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);
    }
...