#postgresql #left-join #union
#postgresql #левое соединение #объединение
Вопрос:
У меня есть оценка основной таблицы. Я уже объединил эту таблицу с таблицей классов. Теперь я хочу присоединиться к другой таблице, инструктор.
Оценка
ClassID | Средняя градация |
---|---|
1 | A |
2 | B |
3 | B |
Класс
ID | Класс |
---|---|
1 | Математика |
2 | Английский |
3 | История |
4 | Испанский |
5 | Наука |
Инструктор
Класс | Инструктор |
---|---|
1 | Алиса |
2 | Боб |
4 | Чарли |
Текущий запрос, который у меня есть
select * from Grade left join Class on Grade.ClassID = Class.ID
Могу ли я каким-либо образом оставить соединение Instructor
поверх этого запроса, чтобы в моей таблице было следующее?
ID | Класс | Средняя градация | Инструктор |
---|---|---|---|
1 | Математика | A | Алиса |
2 | Английский | B | Боб |
3 | История | B | |
4 | Испанский | Чарли |
Не включая 5-Science, поскольку у него нет ни оценки, ни преподавателя.
По другим причинам я должен сначала присоединиться к Grade.
Спасибо!
Комментарии:
1. Вы пишете, что должны присоединиться к первому классу — вы имеете в виду, что по какой-то причине это должна быть первая таблица в части «от»? Кроме того, я правильно вас понимаю — вы хотите видеть только классы, у которых есть либо оценка, либо инструктор обоих классов. Если ни один из них не доступен — класс не должен отображаться?
2. @JuliusTuskenis Извините, это было непонятно. Но да, на оба вопроса.
Ответ №1:
Нет, вы не можете использовать LEFT JOIN Instructor поверх имеющегося у вас запроса, потому что первая таблица (оценка) ограничивает количество записей, которые вы получаете в результате при использовании левых объединений. Вы не можете получить NULL из таблицы оценок в результате, если у вас только левое соединение.
Другие варианты:
Необходимость начинать с оценки ограничивает некоторые наиболее очевидные варианты, но я все еще могу придумать два:
- Использование right join для присоединения к классу, а затем присоединение к инструктору. Таким образом, мне нужно отфильтровать классы без инструкторов и оценок в части WHERE:
select
Class.ID,
Class.Class,
Grade.AverageGrade,
Instructor.Instructor
from
Grade
right join Class on Grade.ClassID = Class.ID
left join Instructor on Class.ID = Instructor.Class
where
Grade.AverageGrade is not null
or instructor.Instructor is not null
- Использование полного объединения grade и instructor возвращает нужные мне записи, поэтому позже фильтрация не требуется, но класс должен быть объединен с использованием идентификатора из grade или instructor, поскольку один из них может быть нулевым.
select
Class.ID,
Class.Class,
Grade.AverageGrade,
Instructor.Instructor
from
Grade
full join Instructor on Grade.ClassID = Instructor.Class
join Class on coalesce(Grade.ClassID, Instructor.class) = Class.ID
Они оба возвращают один и тот же результат.
Комментарии:
1. Большое спасибо! Я использовал опцию полного объединения. Хотя кажется, что когда я добавил условие для инструктора, например, во время полного объединения
full join Instructor on Grade.ClassID = Instructor.Class and Instructor.ID < 5
,<5
условие не сработало. Он по-прежнему полностью объединяет всех инструкторов, независимо от того, какой идентификатор. Мне пришлось добавить это условие в предложение where . Или при полном объединении я полностью присоединилсяselect * from Instructor where Instructor.ID < 5
. Оба работают, но просто любопытно, почему я не могу использовать его в условии полного соединения.2. @cxc таблица инструктора, как вы определили в вопросе, не имеет идентификатора. Это новый столбец или вы имеете в виду инструктора. Класс? В любом случае — чтобы ответить на ваш вопрос, условия полного объединения описывают, как будут объединены записи из обеих таблиц. Если условие ложно — записи по-прежнему отображаются в результате с нулевыми значениями в других полях таблицы.