Webcodeexpert.com Ответов: 1

Получите все строго совпадающие записи из двух таблиц


У меня есть следующий тип таблиц


Объявите таблицу @tbStudent (StudentId INT, StudentName NVARCHAR(100))
Вставить в @tbStudent (StudentId , StudentName)
Значения (101,"Джеймс"),(102,"Смит"),(103,"Джексон"),(104,"Питер");

Объявите таблицу @tbStudentCourseDetails (StudentId INT, CourseId INT)
Вставить в @tbStudentCourseDetails (StudentId , CourseId)
Ценности (101,1),(101,3),(101,6),
(102,4),(102,3),
(103,5),(103,3),
(104,1),(104,3),
(105,1);


Объявить таблицу @tbCourseDone (CourseId INT)
Вставить в @tbCourseDone(CourseId)
Значения (1),(3);

Выберите * из @tbStudent
Выберите * из @tbStudentCourseDetails
Выберите * из @tbCourseDone


Теперь мне нужно получить записи StudentId, StudentName,CourseId, где студент прошел все курсы, определенные в таблице @tbCourseDone, т. е. 1 и 3

Выход должен быть
StudentId StudentName CourseId
101 Джеймс 1
101 Джеймс 3
104 Петр 1
104 Петр 3

Что я уже пробовал:

Я попробовал в операторе, но он извлекает записи студента, где любой курс соответствует

Я также попробовал ниже запрос и получил желаемый результат:

DECLARE @RecCount int=(SELECT count(*) FROM @tbCourseDone)

;С микте
АС
(
Выберите EM.StudentId
От @tbStudent EM
Внутреннее соединение @tbStudentCourseDetails teld на EM.StudentId = teld.StudentId
Внутреннее соединение @tbCourseDone t ON t.CourseId=teld.Идентификатор_курса
Группа по EM.StudentId имея COUNT(Em.StudentId)=@RecCount
)

Выберите EM.StudentId,StudentName,teld.Идентификатор_курса
От @tbStudent EM
Внутреннее соединение @tbStudentCourseDetails teld на EM.StudentId = teld.StudentId
Внутреннее соединение @tbCourseDone t ON t.CourseId=teld.Идентификатор_курса
Внутреннее соединение myCTE cte на cte.StudentId=EM.StudentId


Но это не оптимизированный запрос, и я думаю, что его можно сократить. Пожалуйста, помогите мне получить этот результат.

1 Ответов

Рейтинг:
6

Richard Deeming

Возможно, есть более простой способ сделать это, но первое, что приходит на ум, - это двойной NOT EXISTS тест:

SELECT
    S.StudentId,
    S.StudentName,
    C.CourseId
FROM
    @tbStudent As S
    INNER JOIN @tbStudentCourseDetails As C
    ON C.StudentId = S.StudentId
WHERE
    -- Only return details for the required courses:
    Exists
    (
        SELECT 1
        FROM @tbCourseDone As D
        WHERE D.CourseId = C.CourseId
    )
And
    -- Exclude students who haven't done all required courses:
    Not Exists
    (
        SELECT 1
        FROM @tbCourseDone As D
        WHERE Not Exists
        (
            SELECT 1
            FROM @tbStudentCourseDetails As C2
            WHERE C2.CourseId = D.CourseId
            And C2.StudentId = S.StudentId
        )
    )
ORDER BY
    S.StudentId,
    C.CourseId
;


Webcodeexpert.com

Спасибо за ваше решение. Это хорошо сработало. Но я чувствую, что ваш и мой запрос могут быть короткими. Я не знаю, как это сделать. Я жду каких - то других решений.