0

NOT IN コンポーネントを持つ複数テーブル結合を実行しようとしています。テーブルは

役職 -> 用語関係 -> 用語

Post
  has_many :term_relationships
  has_many :terms, :through => :term_relationships

TermRelationship
  belongs_to :post
  belongs_to :term

Term
  has_many :term_relationships
  has_many :posts, :through => :term_relationships

目標は、「おすすめ」の投稿以外のすべての投稿を取得することです。私の現在のクエリは次のようになります。

WpPost.includes(:terms).where("terms.term NOT IN (?)", ["featured"])

これは、添付された唯一の用語が「特集」である場合にうまく機能します。投稿が「featured」と「awesome」に属している場合、「awesome」であるため表示されます。

とにかく行を完全に除外するには?サブクエリが必要ですか?もしそうなら、どうすればレールでそれを行うことができますか?

皆さんありがとう!ジャスティン

4

2 に答える 2

1

を誤用しincludesます。参加するためではなく、熱心な読み込みのためです!

しかし、あなたはそのアプローチについて正しいです。それはあなたの場合に使用することができます。NOT IN (?)ただし、Railsは、論理的であっても、ネストされた要求を発行しません。代わりに2つのクエリを取得します(NOT IN (id1, id2....,)の代わりに取得しますNOT IN (SELECT ....))。

だから私はあなたがsqueelgemを使うことをお勧めします:

通常のARコード(squeelでプリティフィケーションすることもできます):

featured_posts = WpPost.joins(:terms).where(terms:{term: ['featured']}).uniq

次に、sqeelのパワーを使用します。

WpPost.where{id.not_in featured_posts}

inそしてnot_inまた別名で>>あり、<<しかし私は誰も怖がらせたくありませんでした)

ブロックの使用と記号の欠如に注意してください。


SQLiteでのChinookデータベースに 基づくいくつかの測定:

> Track.all
  Track Load (35.0ms)  SELECT "Track".* FROM "Track"

joinsとの関係like

oldie = Track.joins{playlists}.where{playlists.name.like_any %w[%classic% %90%]}

ここにありNOT INます:

> Track.where{trackId.not_in oldie}.all
  Track Load (37.5ms)  SELECT "Track".* FROM "Track" WHERE "Track"."trackId" 
  NOT IN (SELECT "Track"."TrackId" FROM "Track" INNER JOIN "PlaylistTrack" ON
    "PlaylistTrack"."TrackId" = "Track"."TrackId" INNER JOIN "Playlist" ON 
    "Playlist"."PlaylistId" = "PlaylistTrack"."PlaylistId"
     WHERE (("Playlist"."name" LIKE '%classic%' OR "Playlist"."name" LIKE '%90%')))

ご参考までに:

Track.where{trackId.not_in oldie}.count # => 1971
Track.count # => 3503
# join table:
PlaylistTrack.count # => 8715

結論:によって引き起こされるオーバーヘッドはわかりませんNOT IN。35.0と37.5の違いは目立ちません。35.0が37.5になることはほとんどなく、その逆もあります。

于 2012-05-30T06:30:13.797 に答える
0

1 つのオプションは、OUTER JOIN を実行し、そこに注目の引数を配置することです。次に、用語が結合されていないすべての投稿を選択するだけです。単純な「Railsの方法」でそれを行う方法はわかりませんが、追加のSQLを使用すると、次のように実行できます。

Post.joins("LEFT OUTER JOIN term_relationships ON posts.id = term_relationships.post_id
            LEFT OUTER JOIN terms ON term_relationships.term_id = terms.id AND terms.term = ?", "featured").
     where("terms.id IS NULL")
于 2012-05-30T05:54:47.123 に答える