1

私が望むのは、関連付けを通じてhabtm関連付けられた「fra」言語のみを持つすべてのメディアを照会することです。現在、このクエリはMedia、["fra", "eng"] のように "fra" を含むインスタンスを返します。Postgresを使用しています。

したがって、(1) 言語 'x' のみを含むメディアを見つけたい (2) 言語 'x' と 'y' を正確に含むメディアを見つける (3) 言語 'x' と 'y' を正確に含むメディアを見つける正確には言語「x」、「y」、「z」など。

class Media < ActiveRecord::Base
    has_and_belongs_to_many :audio_language_records, :join_table => "audio_languages_media", :class_name => "Language"
end

class Language < ActiveRecord::Base
  attr_accessor :code
end

私はこれを試しましたが、「fra」だけでなく「fra」を含むすべてのメディアを返します

Media.joins(:audio_language_records).where("languages.code = ? AND languages.code != ?", "fra", "eng")

以下は意図したとおりに機能せず、同じ結果を返します

Media.joins(:audio_language_records).where("languages.code IN (?) AND languages.code NOT IN (?)", ["fra"], ["eng"])
4

2 に答える 2

1

したがって、'eng' の language.code が存在するメディアを見つける必要がありますが、結合テーブルには同じ media_id で異なる language_id のエントリはありません。

SELECT * FROM media m1
  JOIN audio_languages_media alm1 ON alm1.media_id = m1.id
  JOIN languages l1 ON alm1.language_id = l1.id 
  WHERE NOT EXISTS(
    SELECT 1 FROM audio_languages_media alm2
    WHERE alm1.language_id != alm2.language_id
    AND alm1.media_id = alm2.media_id
  )
  AND l1.code = 'eng';

これが適切なデータベース クエリであるかどうかをお知らせください。AREL のお手伝いをさせていただきます。

編集:少なくとも「eng」と「fra」にあるメディアを見つけたい場合のクエリ

SELECT * FROM media m1
  WHERE(
    SELECT count(*) FROM audio_languages_media alm2
    JOIN languages l2 ON alm2.language_id = l2.id
    WHERE l2.code in ('eng','fra')
    AND alm2.media_id = m1.id
  ) > 1;

編集:@chinshrのクエリを追加

正確に「eng」と「fra」しかないメディアが必要な場合

SELECT * FROM media m1
  WHERE(
    SELECT count(*) FROM audio_languages_media alm2
    JOIN languages l2 ON alm2.language_id = l2.id
    WHERE l2.code IN ('eng','fra')
    AND alm2.media_id = m1.id
    AND (
      SELECT count(*) FROM audio_languages_media alm2 
      WHERE alm2.media_id = media.id
    ) = 2
  ) = 2;

このクエリは、IN 配列に追加/削除し、最後のカウントを IN 配列の要素数と等しくなるように調整することで、多かれ少なかれ言語に合わせて微調整できます。

これが確実に機能するには、audio_languages_media(media_id, language_id); に一意のインデックスが必要です。

于 2013-03-14T11:56:50.580 に答える
0

行ごとに1つの値しかないため、「fra」であるすべての値を「eng」などにすることはできません。2行をチェックする必要があります。これは、たとえば次のようにSQLで実行できます。

SELECT * 
FROM languages t1
LEFT JOIN languages t2
    ON t1.id=t2.id AND t2.code="eng"
WHERE t1.code="fra" AND t2.code IS NULL;
于 2013-03-14T01:24:55.727 に答える