简体   繁体   中英

Get records for last month

I need to get the customer id, number and amount of orders for the last month.

Paper::select('customer_id', DB::raw('SUM(price) as `sum`')
    ,DB::raw('COUNT(*) as `orders_per_month`'))
    ->where('created_at', '>=', Carbon::now()->startOfMonth())
    ->groupBy('customer_id')->get()

I tried so, but if the last month the client has no orders, it will not be selected

Try COALESCE:

DB::raw('COALESCE(COUNT(*), 0) as `orders_per_month`')

This function allows you define a default value when otherwise it is NULL.

http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce

UPDATE:

I think if you are selecting only customer which has orders the last month, then definitely you will not get those customers without orders.

You can achieve what you need with something like:

mysql> select * from cu;
+----+----------+
| id | name     |
+----+----------+
|  1 | Google   |
|  2 | Yahoo    |
|  3 | Mirosoft |
+----+----------+
3 rows in set (0.00 sec)

mysql> select * from so;
+----+-------------+---------------------+-------+
| id | customer_id | created_at          | price |
+----+-------------+---------------------+-------+
|  1 |           1 | 2016-08-23 12:12:12 |     2 |
|  2 |           1 | 2016-09-24 12:14:13 |     3 |
|  3 |           2 | 2016-09-25 00:00:00 |     5 |
|  4 |           2 | 2016-09-12 09:00:00 |     3 |
+----+-------------+---------------------+-------+
4 rows in set (0.00 sec)

mysql> select cu.id as customer_id, coalesce(sum(so.price),0) as total, coalesce(count(so.customer_id),0) as orders_per_month from cu left join so on (cu.id = so.customer_id) where so.created_at >= '2016-09-01 00:00:00' or so.created_at is null group by cu.id;
+-------------+-------+------------------+
| customer_id | total | orders_per_month |
+-------------+-------+------------------+
|           1 |     3 |                1 |
|           2 |     8 |                2 |
|           3 |     0 |                0 |
+-------------+-------+------------------+
3 rows in set (0.00 sec)

However, the resulting query would not be very efficient as one way or another, you will have to scan all your customers and JOIN to get those without orders. It might be faster to get a list of customers with orders and without order separately and merge them with UNION or via your application code.

mysql> select customer_id, sum(total) as total, sum(orders_per_month) as orders_per_month from (select id as customer_id, 0 as total, 0 as orders_per_month from cu union all select customer_id, sum(so.price) as total, count(so.customer_id) as orders_per_month from so where created_at >= '2016-09-01 00:00:00'group by customer_id) agg group by customer_id;
+-------------+-------+------------------+
| customer_id | total | orders_per_month |
+-------------+-------+------------------+
|           1 |     3 |                1 |
|           2 |     8 |                2 |
|           3 |     0 |                0 |
+-------------+-------+------------------+
3 rows in set (0.00 sec)

Try this

Paper::select('customer_id', DB::raw('SUM(price) as `sum`'),
             DB::raw('COUNT(*) as `orders_per_month`')
       )
     ->whereMonth('created_at', Carbon::now()->month)
     ->whereYear('created_at', Carbon::now()->year)
     ->groupBy('customer_id')->get()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM