SQL如何筛选每个user_id前5条预订记录并正确聚合总金额
需求说明
提取表fact_flight_sales中每个user_id按booking_created_time排序的前5条预订记录,再对这部分数据做聚合计算,要求每个用户仅返回前5条记录,总金额仅统计这5条的金额总和。
原有SQL问题梳理
- 未对按用户排序后的记录做序号过滤,导致部分用户返回的记录数超过5条
- 关联的子查询覆盖了用户全量订单数据,聚合计算时统计的是用户所有订单的总金额,而非前5条的金额
- 冗余的join和group by逻辑增加了计算复杂度,同时引入了结果偏差
修正后的SQL代码
WITH user_order_rank AS ( SELECT user_id, booking_created_time, booking_price_amount, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY booking_created_time ASC) AS booking_sequence FROM fact_flight_sales -- 保留原有去重逻辑,无需去重可删除该行 GROUP BY user_id, booking_created_time, booking_price_amount ), user_top5_orders AS ( SELECT user_id, booking_created_time, booking_price_amount, booking_sequence, -- 仅统计当前用户前5条订单的总金额 SUM(booking_price_amount) OVER (PARTITION BY user_id) AS total_booking_price_amount FROM user_order_rank -- 过滤每个用户的前5条记录 WHERE booking_sequence <= 5 ) SELECT user_id, booking_sequence, booking_created_time::date AS booking_created_date, booking_price_amount, total_booking_price_amount FROM user_top5_orders -- 筛选前5条总金额大于25000000的用户,不需要可删除该行 WHERE total_booking_price_amount > 25000000 ORDER BY total_booking_price_amount DESC, booking_sequence ASC;
修正逻辑说明
- 先用CTE
user_order_rank对每个用户的预订记录按创建时间升序排序,生成序号,保留了原SQL的去重逻辑,不需要去重可删除对应的group by语句 - 第二层CTE
user_top5_orders过滤出序号<=5的记录,直接用窗口函数统计每个用户前5条的总金额,不需要额外关联全量数据 - 最终查询层可按需添加过滤条件,输出符合要求的结果即可
内容的提问来源于stack exchange,提问作者Rivaldo
相关产品推荐
相关产品推荐

