Как выбрать конкретную запись из отношений «многие ко многим», которая не содержит определенного элемента в Rails 2? - PullRequest
0 голосов
/ 14 декабря 2010

Я застрял с этим на пару часов. Это может быть быстрое решение, но мой мозг перегрелся. Хорошо, вот оно.

У меня есть модели Session и SessionType, которые имеют отношения «многие ко многим» друг с другом следующим образом.

class Session < ActiveRecord::Base
  ...
  has_and_belongs_to_many :session_types
  ...
end

class SessionType < ActiveRecord::Base
  ...
  has_and_belongs_to_many :sessions
  ...
end

То, что я хочу, это получить сеанс, который не содержит какого-либо определенного session_type, например,

Session.find(:all, :joins => [:session_types], :conditions => ["session_types.id <> 44"])

Это не работает для меня, так как вышеупомянутый запрос все равно даст мне сеансы, у которых session_types.id "44" во многих его ассоциациях из-за характера отношений "многие ко многим".

Также следующий код mysql также не работает.

select sessions.* from sessions
INNER JOIN `session_types_sessions` ON `session_types_sessions`.session_id = `sessions`.id 
WHERE (  session_types_sessions.session_type_id NOT IN (44))
GROUP BY sessions.id

Любая помощь будет оценена.

Спасибо.

Ответы [ 3 ]

1 голос
/ 14 декабря 2010

Сначала выберите те сеансы, которые имеют тип 44:

session_types_44 = Session.find(:all, :joins => :session_types, 
  :conditions => { :"session_types.id" => 44 }).uniq

и выберите сеансы, которые не подпадают под вышеуказанное:

sessions_without_type_44 = Session.find(:all, 
  :conditions => "id NOT IN (#{session_types_44.join(",")})")

Вы должны быть осторожны с этим, потому что если session_types_44 - пустой массив, вы получите ошибку SQL.

И чтобы ответить на ваш второй вопрос:

знаете ли вы, как я мог бы изменить SQL для фильтрации типа "получить мне сеансы, которые имеют session_type_id '43', но они не должны иметь '44'

Возьмите результат из sessions_without_type_44 и используйте его. Сначала выберите SessionType с 43 и через сопоставление получите все сеансы, которые принадлежат этому SessionType, и их идентификаторы находятся в пределах sessions_without_type_44:

SessionType.find(43).sessions.all(:conditions => { 
  :id => sessions_without_type_44 })
1 голос
/ 14 декабря 2010

Попробуйте это:

SELECT sessions.*
FROM sessions
LEFT JOIN session_types_sessions ON session_types_sessions.session_id = sessions.id AND session_types_sessions.session_type_id = 44
WHERE session_types_sessions.session_id IS NULL
0 голосов
/ 14 декабря 2010

Попробуйте это:

Session.all(
  :include => :session_types,
  :conditions => ["session_types.id IS NOT NULL AND session_types.id != ?", 44])
)

Опция include использует LEFT JOIN, поэтому этот запрос будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...