如何用SQL获取用户最后访问的去重优惠券记录?
解决CodeIgniter中GROUP BY返回非最新记录的问题
你的问题核心在于:GROUP BY coupon_id会将相同优惠券ID的记录归为一组,但在没有指定聚合规则时,数据库会返回每组中任意一条的id(而非你需要的最新浏览记录的id)。比如你数据里coupon_id=65的最新记录是id=4,但结果里却出现了coupon_id=58的id=2,这就是因为GROUP BY随机取了该分组里较早的一条记录。
你想要的是「指定用户最近浏览过的4个不同优惠券,且每个优惠券只保留最新的那条浏览记录」,用DISTINCT确实达不到这个需求——因为DISTINCT只是去重结果行,无法帮你筛选出每个优惠券的最新记录。下面是两种可行的CodeIgniter实现方案:
方案一:子查询获取每个优惠券的最新记录ID
先通过子查询找出每个coupon_id对应的最大id(也就是最新浏览的那条记录),再基于这些ID查询最终结果:
// 编译子查询:获取每个coupon_id的最大id $this->db->select_max('id'); $this->db->from('user_viewed_offer'); $this->db->where('user_id', $user_id); $this->db->group_by('coupon_id'); $latest_ids_subquery = $this->db->get_compiled_select(); // 查询这些最新id的记录,按id倒序取4条 $this->db->select('id'); $this->db->from('user_viewed_offer'); $this->db->where_in('id', $latest_ids_subquery); $this->db->order_by('id', 'desc'); $this->db->limit(4); $data['coupons'] = $this->db->get()->result(); var_dump(json_encode($data['coupons'])); exit();
方案二:用窗口函数(适用于MySQL 8.0+及其他支持窗口函数的数据库)
如果你的数据库支持窗口函数,可以用ROW_NUMBER()给每个优惠券的记录按id倒序编号,然后只取编号为1的(即最新的那条):
$this->db->select('id'); $this->db->from("( SELECT id, coupon_id, ROW_NUMBER() OVER(PARTITION BY coupon_id ORDER BY id DESC) AS row_num FROM user_viewed_offer WHERE user_id = {$user_id} ) AS temp_table"); $this->db->where('row_num', 1); $this->db->order_by('id', 'desc'); $this->db->limit(4); $data['coupons'] = $this->db->get()->result(); var_dump(json_encode($data['coupons'])); exit();
这两种方案都会返回你期望的id=4、5、6、7的记录,解决GROUP BY返回非最新记录的问题。
内容的提问来源于stack exchange,提问作者F.Joodaki
相关产品推荐
相关产品推荐

