1

私が構築しているRails3アプリには、次の3つのクラスがあります。

class Instrument < ActiveRecord::Base
  has_many :parts
  has_many :pieces, through: :parts
end    
class Part < ActiveRecord::Base
  belongs_to :instrument
  belongs_to :piece
end
class Piece < ActiveRecord::Base
  has_many :parts
  has_many :instruments, through: :parts
end

関連する楽器が任意の楽器セットのサブセットであるすべてのピースを選択する方法を探しています。

混乱を避けるために、例を挙げます。

  • 楽器付きのピース(id:1):[1,2,3]、
  • [1,2,3,4]のPiece(id:2)
  • ピース(id:3)と[1,3,4]
  • ピース(id:4)と[2]、

somequery(1,2,3,4)somequery(1,2,3)4つのピースすべて、 1と4somequery(1,3,4)のみ、ピース3と4のみを生成する必要がありsomequery(2)ます。

私はrails3.2を使用しており、railsのソリューションは素晴らしいですが、sqlも問題なく、できればpostgresですが、これに対するmysql固有のソリューションがあれば、それも問題ありません。さらに、私は比較的小さなデータベース(1000以上のピース、50の機器、15.000のパーツ)を使用していないため、クエリの効率が最適でない場合でも問題はありません。

最後の免責事項として、私はRuby / Railsでの自分の道を知っていますが、SQLではかなり環境に配慮しています。

助けてくれてありがとう!

4

2 に答える 2

2
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp;

SET search_path='tmp';


CREATE TABLE instrument
        ( id INTEGER NOT NULL PRIMARY KEY
        , zname varchar
        );
INSERT INTO instrument(id, zname) VALUES
(1, 'instrument_1'), (2, 'instrument_2')
, (3, 'instrument_3'), (4, 'instrument_4');

CREATE TABLE piece
        ( id INTEGER NOT NULL PRIMARY KEY
        , zname varchar
        );
INSERT INTO piece(id, zname) VALUES
(1, 'piece_1'), (2, 'piece_2'), (3, 'piece_3'), (4, 'piece_4');

CREATE TABLE has_part
        ( piece_id INTEGER NOT NULL
        , instrument_id INTEGER NOT NULL
        , PRIMARY KEY (piece_id,instrument_id)
        );

INSERT INTO has_part(piece_id,instrument_id) VALUES
(1,1), (1,2), (1,3)
, (2,1), (2,2), (2,3), (2,4)
, (3,1), (3,3), (3,4)
, (4,2)
        ;

純粋な sql (二重否定ではありませんNOT EXISTS , NOT IN():

SELECT zname
FROM piece pp
WHERE NOT EXISTS (
        SELECT * FROM has_part nx
        WHERE nx.piece_id = pp.id
        AND nx.instrument_id NOT IN (1,2,3)
        )
        ;
于 2012-06-20T13:34:37.813 に答える
0

次のようなものを試してください。

Piece.joins(:instruments).where(:instruments => {:id => [1, 2, 3, 4]})

これにより、2つのテーブルを結合し、必要なIDを持つインストゥルメントを持つピースを選択し、最後にそれらをActiveRecordオブジェクトにラップするクエリが作成されるため、後で必要なことを行うことができます。

于 2012-06-20T11:41:03.783 に答える