Example 6. GROUP BY Raw Expression

Example 6. GROUP BY Raw Expression

2024-09-05 وقت القراءه : 3 دقائق

"أحيانًا قد نحتاج إلى أكثر من مجرد عمود بسيط. على سبيل المثال، نرغب في تجميع طلباتنا حسب الشهر الذي تم إنشاؤها فيه. كما بالصورة التالية"

للحصول على البيانات كما بالصوره أعلاه

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. يُستخدم هنا لـ:

  • استخراج الشهر من عمود orders.order_time باستخدام دالة MySQL month().
  • حساب الكمية الإجمالية للمنتجات المطلوبة في كل شهر باستخدام sum(order_p.quantity).
  • حساب الإجمالي المالي للطلبات في كل شهر باستخدام sum(orders.total).
  • عد الطلبات المتميزة باستخدام count(distinct id) للحصول على عدد الطلبات الفريدة في كل شهر.


->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

إضافة تعليق
Loading...