оставленное соединение не возвращает правильную информацию - PullRequest
0 голосов
/ 27 мая 2018

У меня есть таблица courses и таблица volunteer_rosters.courses содержит список всех курсов, а volunteer_rosters содержит список добровольцев, преподающих / помогающих на курсе.

Я хочу написать запрос, который возвращает список всех курсов, которые не не назначены добровольцы.Вот что происходит:

courses     
-------     
id 
 1  
 3  
 4  
 5  
 6  

volunteer_courses
-----------------
id 1 course_id 1  
id 2 course_id 1  
id 3 course_id 1  
id 5 course_id 3  
id 6 course_id 3  

Все приведенные ниже запросы возвращают
course_id 3
course_id 4
course_id 5

Почемуcourse_id 1 (правильно) пропущен, но course_id 3 не является ???

Course.joins("LEFT JOIN student_rosters ON courses.id = student_rosters.course_id where student_rosters.course_id is null")

Course.joins("LEFT JOIN student_rosters ON courses.id = student_rosters.course_id").where(student_rosters: {id: nil})

Course.includes(:student_rosters).references(:student_rosters).where(student_rosters: {id: nil})

Course.includes(:student_rosters).references(:student_rosters).where('student_rosters.id = ?', nil)

Course.joins("LEFT JOIN student_rosters ON courses.id = student_rosters.course_id").where(student_rosters: {id: nil})

Тот же самый точный вопрос, но ни одно из решений не работает для меня:

ЛЕВОЕ НАРУЖНОЕ СОЕДИНЕНИЕ в Rails 4

Ответы [ 2 ]

0 голосов
/ 27 мая 2018

Хотя нет необходимости использовать join s, использование not in опасно для подзапроса.Он не делает то, что вы действительно хотите.Если какая-либо строка в подзапросе возвращает значение NULL, то внешний запрос ничего не возвращает.Строк вообще нет.

По этой причине я настоятельно рекомендую использовать not exists и избегать not in с подзапросами:

select c.id
from Courses c
where not exists (select 1 from volunteer_courses vc where vc.course_id = c.id);

или left join версия:

select c.id
from Courses c left join
     volunteer_courses vc 
     on vc.course_id = c.id
where vc.course_id is null;

Кроме того, оба из них могут использовать индекс на volunteer_courses(course_id).

0 голосов
/ 27 мая 2018

Нет необходимости использовать join.Попробуйте это:

select id from Courses
where id not in (select course_id from volunteer_courses)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...