首页 > 解决方案 > 当记录不存在时忽略 WHERE 子句

问题描述

我知道有很多标题相似的主题,但它们似乎与其他案例有关。我有 3 张桌子:

song:
  id
  title


playlist_song:
  id
  song_id
  playlist_id


stats_record:
  id
  type // enum SONG_LIKED/SONG_DISLIKED/...
  user_id
  entity_id // id of an entity stats record refers to

我使用playlist_song将歌曲存储在播放列表中,使用stats_record捕获诸如播放/喜欢/不喜欢之类的内容。

我有一个功能,我想向用户展示他们从不喜欢或不喜欢的歌曲。表示 stats_record要么不存在,要么不存在其类型!= SONG_LIKED/SONG_DISLIKED(针对该特定用户!)

但是,当我尝试构建此查询时,它会显示其他用户也从未喜欢过的歌曲(我只关心当前用户)。我的查询如下所示:

select s.title, sr.type 
from song s
left join playlist_song ps on ps.song_id = s.id
left join stats_record sr on sr.entity_id = ps.id
where ps.playlist_id = 'a686e0da-750f-11eb-9da1-bf79c63bacf7' 
  and ((sr.user_id = 'a26e23b4-7483-11eb-986b-5fc23c9ef85c' 
  and (not sr.type = 'SONG_LIKED' 
  and not sr.type = 'SONG_DISLIKED')) or sr.id is null);

我想要实现的是“如果 stats_record 存在,检查它是否不是 SONG_LIKED/DISLIKED,否则忽略”

标签: sqlpostgresql

解决方案


我没有对此进行测试,但我认为反加入会起作用:

select s.title, sr.type 
from song s
left join playlist_song ps on ps.song_id = s.id
where
  ps.playlist_id = 'a686e0da-750f-11eb-9da1-bf79c63bacf7' and
  not exists (
    select null
    from stats_record sr
    where
      sr.entity_id = ps.id and
      sr.user_id = 'a26e23b4-7483-11eb-986b-5fc23c9ef85c' and
      sr.type in ('SONG_LIKED', 'SONG_DISLIKED') -- this might be unnecessary
  )

这个结构也非常有效,并且可以容忍重复,尽管我认为在这个例子中你不会有任何重复。

假设这可行,请尝试省略最后一个 where 子句 ( sr.type in...)。我不认为你会需要它。


推荐阅读