Как я могу переписать запрос с объединениями, чтобы показать критерии, которые не были включены в мой поиск?

#tsql

#tsql

Вопрос:

Здесь меня беспокоит другой запрос.

 Select S.ID,S.Name,S.Surname,B.Title,SB.DateAndTimeIssued FROM Students S
INNER JOIN StudentBooks SB ON
S.ID = SB.StudentID
INNER JOIN Books B
ON B.ID = SB.BookID
WHERE B.ID = @BookID
  

Результаты:

 1 | asd   | asd   | Book      | 2011-10-12 18:31:40.557
1 | asd   | asd   | Gray Book | 2011-10-12 18:36:26.950
1 | asd   | asd   | Gray Book | 2011-10-12 18:36:34.137
  

Объяснение: Этот запрос возвращает мне имена и фамилии всех студентов, у которых была книга с определенным идентификатором, выданным им. Также отображаются дата и выданная им книга.

Проблема в том, что эти книги в таблице выше были назначены только одному студенту. Как я могу переписать этот запрос, чтобы показать мне, какие студенты не получили конкретную книгу с идентификатором @BookID ? Когда я использую WHERE NOT B.ID = @BookID , он отправляет мне только имена студентов, которые не получили книгу, но получили книгу в прошлом.

Моя попытка:

 SELECT S.Name,S.Surname FROM Students S
INNER JOIN StudentBooks SB
ON SB.StudentID = S.ID
INNER JOIN Books B
ON B.ID = SB.BookID
WHERE NOT SB.BookID = @BookID
  

Мне нужны имена студентов, которые вообще не получили книгу. Students, StudentBooks и Books — это отдельные таблицы, Students и Studentbooks находятся в отношениях «многие ко многим», поскольку книга может быть переиздана им позже, или копия книги может быть переиздана им, если они потеряли свои

Ответ №1:

Я думаю, вы можете объединить таблицу books и student books и получить все идентификаторы студентов, которые взяли книгу, а затем искать любой идентификатор в таблице student, которого нет в комбинации идентификаторов, которые вы получаете из первой таблицы (books и student books)

 SELECT S.ID,S.Name,S.Surname,B.Title,SB.DateAndTimeIssued 
FROM Students S 
WHERE s.id NOT IN (SELECT id 
                   FROM Books b 
                   JOIN StudentBooks sb 
                   ON b.ID = sb.BookID
                   WHERE b.ID = @BookID)
  

Комментарии:

1. Это сработало очень хорошо, большое вам спасибо. Вы сохранили мой rim. Теперь я могу закончить свой проект: D

2. Все, что я добавил в ваш код, это предложение where в подзапросе, чтобы посмотреть, где идентификатор книги = @BookID. Я получил желаемые результаты 🙂

Ответ №2:

Внешнее объединение, чтобы получить всех студентов, может быть, что-то вроде:

 Select S.ID,S.Name,S.Surname,B.Title,SB.DateAndTimeIssued
FROM Students S
LEFT OUTER JOIN StudentBooks SB 
    ON S.ID = SB.StudentID
    AND SB.BookId = @BookId
LEFT OUTER JOIN Books B
    ON B.ID = SB.BookID
  

Который не будет включать заголовок для тех студентов, у которых нет записи в студенческой книжке, если вам нужен заголовок для каждой записи:

 Select S.ID,S.Name,S.Surname,B.Title,SB.DateAndTimeIssued
FROM Students S
CROSS JOIN (select title from Books where Id = @BookId) B
LEFT OUTER JOIN StudentBooks SB
    on SB.StudentId = S.ID
    and SB.BookId = @BookId
  

Но я не понимаю результатов, которые вы показываете:

 1 | asd   | asd   | Book      | 2011-10-12 18:31:40.557
1 | asd   | asd   | Gray Book | 2011-10-12 18:36:26.950
1 | asd   | asd   | Gray Book | 2011-10-12 18:36:34.137
  

Насколько я понимаю ваш запрос, результат должен быть для одной конкретной книги на основе Book.Id = @BookID , но вы показываете два разных названия книг: «Книга» и «Серая книга».

Как написано, ни один из этих запросов не обобщается для получения записей более чем для одного book.id за раз.