2013-03-13 3 views
1

То, что я хочу, - это запрос для всех носителей, которые имеют только «fra» язык, связанный с ассоциацией habtm. В настоящее время этот запрос возвращает Media экземпляры, которые включают «fra», так, например, ["fra", "eng"]. Я использую Postgres.Все включено, если включено, если и только если запрос не работает с Rails и Postgres

Итак, (1) Я хочу найти носитель, который имеет ровно язык «х» и ни один другой, (2) найти носитель, который имеет именно языки «х» и «у», (3) найти СМИ, что имеет точно Языков «х», «у» и «г» и т.д.

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»

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"]) 
+0

Было бы полезно, если бы вы могли разместить SQL, сгенерированный при выполнении ваших запросов. –

+0

Вы уверены, что 'languages.code =? AND languages.code! =? 'Работает с MySQL? –

+0

@rocket, SQL из первого запроса '' SELECT "media". * FROM "media" INNER JOIN "audio_languages_media" ON "audio_languages_media". "Media_id" = "media". "Id" INNER JOIN "Языки" ON "языки "." id "=" audio_languages_media "." language_id "WHERE (languages.code = 'fra' AND languages.code! = 'eng')" ' – chinshr

ответ

1

Так что вам нужно найти носителя для которого существует language.code из «анг», но нет записей в не присоединиться к таблице для того же media_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'; 

Сообщите нам, если это правильный запрос db, чтобы мы могли помочь с AREL.

Edit: Запрос, когда вы хотите, чтобы найти средства массовой информации, которое, по крайней мере, «анг» и «Фра

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; 

Edit: запросов Добавить @ chinshr в

Если вы хотите носитель, который имеет только именно «рус» и «Фра

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, и регулируя количество в конце равным числу Elemen ts в массиве IN.

Для надежной работы вы должны иметь уникальный индекс на audio_languages_media (media_id, language_id);

+0

Благодаря @cmaitchison, он отлично подходит для одного языка, например. «eng», но он ломается, когда вы хотите запросить все «eng» и «fra», чтобы вернуть все носители с обоими этими языками и изменить последнюю часть запроса на AND l1.code = «eng» AND l1 .code = "fra" – chinshr

+0

Хорошо, это другой запрос, позвольте мне отредактировать мой ответ и добавить его. –

+0

Вы рекомендуете использовать первый запрос для одного языка и запрос секунд для нескольких? или можно ли настроить второй запрос для поддержки> = 1 языков? Параметрирование> 0,> 1,> 2 в зависимости от того, сколько языков передано, не работает. – chinshr

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; 
+0

Спасибо, хотя мы хотим вернуть средства массовой информации, а не языки. – chinshr

+0

@chinshr И вы хотите сделать это в рубине, я только писал, почему ваш запрос не может работать и как справиться с этой его частью. –

+0

Да, я хочу сделать это в ActiveRecord. – chinshr

Смежные вопросы