1

我想要的是查询所有只有通过habtm关联关联的“fra”语言的媒体。目前,此查询返回Media包含“fra”的实例,例如 ["fra", "eng"]。我使用 Postgres。

因此,(1)我想找到完全具有语言“x”而没有其他语言的媒体,(2)找到完全具有语言“x”和“y”的媒体,(3)找到具有正是语言“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

因此,您需要找到存在 language.code 为“eng”但在连接表中没有相同 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

每行只有一个值,因此“fra”的每个值都不能是“eng”或任何其他值。你必须检查两行。它可以像这样在 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 回答