问题
有订单表如下:
orders
-----------------------------------------
id | user_id | amount | created_at
-----------------------------------------
计算订单表中所有用户每个用户最近五次订单的平均值(保留两位小数),并统计平均数相同的用户数。例如:某用户最近五次订单的总金额的平均值为50.0元,订单表中所有平均值为50.0元的用户数
解决
SELECT round(AVG("orders"."amount"),2), user_id, count(*), sum("orders"."amount") FROM "orders" GROUP BY "orders"."user_id"
sql>
--------------------------------------------------
round | user_id | count | sum|
46.75 5 12 561
57.67 18 9 519
33.5 64 6 201
40 55 9 360
-------------------------------------------------
从返回值可以看出来,每个用户的订单数,订单总金额和平均值,但是我们只要最近五次订单的总金额。
因此我们需要先筛选五次订单。
select id, user_id, amount, created_at, row_number() over(partition by user_id ) from orders order by created_at desc
这里是在原表中将每个用户的订单数据按照创建时间排个顺序,并将顺序存在row_number的字段中。
-------------------------------------------------
id | user_id | amount | created_at | row_number |
-------------------------------------------------
981 29 55 2019-03-20 08:43:59.972256 4
876 94 8 2019-03-20 08:43:57.591139 8
850 67 61 2019-03-20 08:43:56.950117 3
840 12 39 2019-03-20 08:43:56.784908 3
808 39 21 2019-03-20 08:43:56.013228 3
779 75 75 2019-03-20 08:43:55.336312 3
723 19 38 2019-03-20 08:43:54.059151 5
715 57 3 2019-03-20 08:43:53.918461 9
这时我们可以筛选出row_number 小于等于 5 的数据就是最近五次的订单数据。
select * from (
select id, user_id, amount, created_at, row_number() over(partition by user_id ) from orders order by created_at desc
) as new_orders where new_orders.row_number <= 5
最后再根据查询的结果算出平均数相同的用户数
select round(AVG(all_orders.amount), 2) as avg_amount, count(*) from(
select * from (
select *, row_number() over(partition by user_id ) from orders order by created_at desc
) as new_orders where new_orders.row_number <= 5
) as all_orders group by all_orders.user_id
最后就得到了数据!
-----------------------------------------------
avg_amount | count
-----------------------------------------------
50 5
64.4 5
21.4 5
26.4 8
52.4 5
72.6 5
66.6 5
29.2 4
38.2 5
45.2 5
59.4 5
78.2 5
58.6 9
59.2 5
32.2 11