在我正在构建的 Rails 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
我正在寻找一种方法来选择所有 Pieces,其中关联的乐器是任意一组乐器的子集。
为了避免混淆我举个例子:given
- Piece(id:1) 与乐器:[1,2,3],
- Piece(id:2) 与 [1,2,3,4]
- [1,3,4] 的片段 (id:3)
- Piece(id:4) 与 [2],
somequery(1,2,3,4)
应该产生所有四个部分,somequery(1,2,3)
只产生 1 和 4,somequery (1,3,4)
仅第 3 部分,somequery(2)
仅第 4 部分。
我正在使用 rails 3.2,rails 中的解决方案会很棒,但 sql 也很好,最好是 postgres,但如果有针对此问题的特定于 mysql 的解决方案,那也很好。此外,我没有使用一个相对较小的数据库(1000 多件,50 件仪器和 15.000 个零件),它没有被大量查询,所以如果查询效率不是最佳的,那也没问题。
作为最后的免责声明,我对 ruby/rails 了如指掌,但对 SQL 还是相当陌生。
感谢您的帮助!
最佳答案
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)
)
;
关于sql - 选择多对多关系中的所有子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11117622/