"أحيانًا قد نحتاج إلى أكثر من مجرد عمود بسيط. على سبيل المثال، نرغب في تجميع طلباتنا حسب الشهر الذي تم إنشاؤها فيه. كما بالصورة التالية"
للحصول على البيانات كما بالصوره أعلاه
public function index() { $orders = Order::selectRaw( 'month(orders.order_time) as month, sum(order_p.quantity) as total_quantity, sum(orders.total) as order_total, count(distinct id) as total_orders' ) ->join( DB::raw('(select order_id, sum(quantity) as quantity from `order_product` group by order_id) as order_p'), 'order_p.order_id', '=', 'orders.id', ) // We are using the month() mysql function to get the month from the order_time column ->groupByRaw('month(orders.order_time)') ->orderBy('month') ->orderBy('total_orders', 'desc') ->get(); return view('groub_by', compact('orders')); }
شرح الكود
$orders = Order::selectRaw( 'month(orders.order_time) as month, sum(order_p.quantity) as total_quantity, sum(orders.total) as order_total, count(distinct id) as total_orders' )
selectRaw: تتيح هذه الطريقة كتابة استعلام SQL خام ضمن استعلام Eloquent. يُستخدم هنا لـ:
->join( DB::raw('(select order_id, sum(quantity) as quantity from `order_product` group by order_id) as order_p'), 'order_p.order_id', '=', 'orders.id', )
يتضمن هذا الانضمام استعلامًا فرعيًا داخل DB::raw() يقوم بالحساب قبل الانضمام:
يقوم الاستعلام الفرعي باختيار البيانات من جدول order_product، ويجمع النتائج حسب order_id، ويحسب مجموع quantity لكل طلب.
يتم بعد ذلك الانضمام مع جدول orders حيث يتطابق order_id مع orders.id، مما يسمح بدمج معلومات كمية المنتج مباشرة مع كل طلب.
->groupByRaw('month(orders.order_time)') ->orderBy('month') ->orderBy('total_orders', 'desc')
groupByRaw: يستخدم تعبير خام لتجميع النتائج حسب الشهر المستخرج من orders.order_time. يضمن ذلك أن جميع العمليات الحسابية التالية تتم ضمن كل شهر.
orderBy: يتم ترتيب النتائج أولًا بترتيب تصاعدي حسب month، الذي يرتب البيانات من يناير إلى ديسمبر.
الترتيب الثاني orderBy('total_orders', 'desc') يرتب الأشهر ضمن كل مجموعة مجمعة حسب عدد الطلبات الإجمالي، بترتيب تنازلي، بحيث يأتي الشهر الذي له أكثر الطلبات أولاً.
لعرض البيانات في blade
<table class="table table-striped table-bordered"> <thead> <tr> <th>Date</th> <th>Total</th> <th>Total Items</th> <th>Total Orders</th> </tr> </thead> <tbody> @foreach ($orders as $order) <tr> <td>{{ $order->month }}</td> <td>${{ number_format($order->order_total, 2) }}</td> <td>{{ $order->total_quantity }}</td> <td>{{ $order->total_orders }}</td> </tr> @endforeach </tbody> </table>
ماذا لو كنا التجميع حسب اليوم وليس الشهر
$orders = Order::selectRaw( 'day(orders.order_time) as day, sum(order_p.quantity) as total_quantity, sum(orders.total) as order_total, count(distinct id) as total_orders' ) ->join( DB::raw('(select order_id, sum(quantity) as quantity from `order_product` group by order_id) as order_p'), 'order_p.order_id', '=', 'orders.id', ) ->groupByRaw('day(orders.order_time)') ->orderBy('day') ->orderBy('total_orders', 'desc') ->get();
كما نرى أنه فقط نستبدل day(orders.order_item) as day عوضا عن mont(orders.order_time) as month