如何在Knex查询中获取无重复ID的有演出艺人?
解决Knex查询返回重复艺人ID的问题
我来帮你分析下问题出在哪,以及怎么解决~
你当前的查询之所以返回重复的艺人ID,核心原因是 distinct('artist_id') 和 select('*') 的组合逻辑不对。当你用 join 关联 event_artist 和 artist 表后,一个艺人如果有多个演出活动,就会生成多条对应不同 event_id 的记录。虽然你指定了 distinct('artist_id'),但SQL里的 DISTINCT 是对所有选中字段的组合去重——你选了 *,就意味着会包含 event_artist 里的 event_id 等字段,这些字段每行都不一样,所以最终结果里还是会出现同一个艺人的多条记录,只是它们的 event_id 不同而已。
下面给你几个可行的解决方案:
方案一:子查询筛选有演出的艺人ID(推荐)
先从 event_artist 中获取所有有演出的艺人ID,再用这些ID去查询艺人表,逻辑清晰且能确保每个艺人只返回一次:
return knex('artist') .whereIn('id', function() { // 子查询获取所有有演出的不重复艺人ID this.select('artist_id').from('event_artist').distinct() }) .offset(offset) .limit(howMany)
方案二:按艺人ID分组
通过 groupBy 按艺人ID分组,强制每个艺人只返回一行(如果后续需要聚合演出相关数据,这个方案会更灵活):
return knex('event_artist') .join('artist', 'event_artist.artist_id', 'artist.id') .groupBy('artist.id') // 按艺人ID分组,确保唯一 .select('artist.*') // 只选择艺人表的字段,避免携带event_artist的重复字段 .offset(offset) .limit(howMany)
方案三:修正DISTINCT与SELECT的字段匹配
如果你想保留原有的join写法,可以调整 distinct 和 select 的字段,只关注艺人表的信息:
return knex('event_artist') .join('artist', 'event_artist.artist_id', 'artist.id') .distinct('artist.id') // 按艺人ID去重 .select('artist.*') // 只获取艺人表的所有字段 .offset(offset) .limit(howMany)
这三个方案都能解决重复ID的问题,你可以根据自己后续的业务需求(比如是否需要同时获取演出相关数据)来选择最合适的一种。
内容的提问来源于stack exchange,提问作者Vlady Veselinov
相关产品推荐
相关产品推荐

