SQL技术咨询:创建含user_id与top5_foods列的表并避免ID重复
解决用户Top5食物标记问题
首先,你遇到的重复user_id问题,核心原因是没有对用户进行聚合判断——之前的CASE语句会逐行处理每个用户-食物的关联记录,所以同一个用户如果有多个食物,就会生成多行结果。我们需要的是对每个用户做一次"是否存在至少一种Top5食物"的判断,确保每个user_id只出现一次。
下面给你两种高效的解决方案:
方法1:使用LEFT JOIN + MAX聚合(直观易理解)
这种方法先把用户的食物列表和Top5食物表做左连接,然后通过分组聚合来判断每个用户是否有匹配的食物:
SELECT uf.user_id, -- 只要用户有一个食物在Top5里,MAX就会返回1,否则0 MAX(CASE WHEN tf.food IS NOT NULL THEN 1 ELSE 0 END) AS top5_foods FROM user_foods uf -- 左连接保留所有用户,匹配Top5食物 LEFT JOIN top5_foods tf ON uf.food = tf.food -- 按用户分组,确保每个user_id唯一 GROUP BY uf.user_id;
方法2:使用EXISTS子查询(性能更优)
如果你的数据量较大,EXISTS子查询通常会更快,因为它只要找到第一个匹配的记录就会停止搜索:
SELECT DISTINCT uf.user_id, CASE -- 检查当前用户是否存在至少一个食物在Top5表中 WHEN EXISTS ( SELECT 1 FROM top5_foods tf WHERE tf.food = uf.food ) THEN 1 ELSE 0 END AS top5_foods FROM user_foods uf;
如果你有单独的用户主表(比如users表只存唯一的user_id),可以直接从主表查询,效率更高:
SELECT u.user_id, CASE WHEN EXISTS ( SELECT 1 FROM user_foods uf JOIN top5_foods tf ON uf.food = tf.food WHERE uf.user_id = u.user_id ) THEN 1 ELSE 0 END AS top5_foods FROM users u;
为什么这两种方法能解决重复问题?
- 方法1通过
GROUP BY uf.user_id强制每个用户只返回一行,MAX()函数会把该用户所有匹配结果中的1保留下来(只要有一个匹配,结果就是1)。 - 方法2用
DISTINCT确保每个user_id唯一,而EXISTS只做存在性判断,不会生成多行结果。
内容的提问来源于stack exchange,提问作者Eli
相关产品推荐
相关产品推荐

