我有一个Album
对象,其中有许多Tracks
。轨道有一个 youtube_uid
列。我想查询包含所有轨道 youtube_uids
的专辑。我知道查找包含轨道的专辑的技术,其中至少有一首轨道带有 youtube_uid
:
Album.left_outer_joins(:tracks).where.not(tracks: { youtube_uid: nil })
查找每首轨道都有 youtube_uid
的专辑的理想查询是什么?
最佳答案
据我了解您的问题,您想要查找所有没有缺少(空)youtube-uid 轨道的专辑。所以据我所知,您需要一个 NOT EXISTS
查询。
在sql中我会写一些类似的东西
select * from albums a
where not exists (select * from tracks where album_id = a.id and youtube_uid is null)
那么我们如何最好地将其转换为 activerecord?我看到两种可能性:
sql = <<-SQL
select * from albums a
where not exists (select * from tracks where album_id = a.id and youtube_uid is null)
SQL
Album.find_by_sql(sql)
虽然这可行,而且对于我来说对 SQL 很熟悉,这感觉很好,它不是很“像 Rails”,所以我们可以改进它吗?
有一个更短的形式:
Album.where("not exists (select * from tracks where album_id = albums.id and youtube_uid is null")
但这仍然感觉有点太冗长了。 幸运的是,存在一种更像 Rails 的方式。在 Rails 4 中你可以这样写:
Album.where(Track.where("album_id = albums.id").where(youtube_uid: nil).exists.not)
在 Rails 5/6 中,这不再可能,你必须编写:
Album.where(Track.where("album_id = albums.id").where(youtube_uid: nil).arel.exists.not)
您可以通过在末尾添加 to_sql
轻松验证这会生成正确的 sql。
关于ruby-on-rails - 仅查找所有 has_many 集合都具有特定列值的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63599068/