Используйте CROSS JOIN
, чтобы получить список каждого студента и каждого предмета, а затем LEFT JOIN
в таблицу Performance
.Затем вы можете использовать предложение HAVING
, чтобы отфильтровать те, которые прошли все предметы, с общей оценкой более 120. Я отфильтрую тех, кто не прошел все, с условным подсчетом, где я считаю только те строки, где mark_obtained
имеет значение NULL
в таблице Performance
(что, как я полагаю, произойдет, если нет строки для студента / предмета).
CREATE TABLE dbo.Student (StudentID int, StudentName varchar(5));
INSERT INTO dbo.Student (StudentID,
StudentName)
VALUES(1,'John'),
(2,'Jack'),
(3,'Jane');
CREATE TABLE dbo.Subject (SubjectID int, SubjectName varchar(10));
INSERT INTO dbo.Subject (SubjectID,
SubjectName)
VALUES(1,'maths'),
(2,'geography'),
(3,'history'),
(4,'physics');
CREATE TABLE dbo.Performance (StudentID int, subject_passed varchar(10), mark_obtained int);
INSERT INTO dbo.Performance (StudentID,
subject_passed,
mark_obtained)
VALUES (1,'maths',40),
(2,'physics',50),
(1,'geography',40),
(3,'maths',80),
(1,'physics',40),
(2,'maths',70),
(2,'geography',40),
(1,'history',30);
GO
SELECT St.StudentID,
St.StudentName,
SUM(P.mark_obtained) AS Marks_obtained
FROM dbo.Student St
CROSS JOIN dbo.Subject Su
LEFT JOIN dbo.Performance P ON St.StudentID = P.StudentID
AND Su.SubjectName = P.subject_passed --This should really be ID
GROUP BY St.StudentID,
St.StudentName
HAVING COUNT(CASE WHEN P.mark_obtained IS NULL THEN 1 END) = 0
AND SUM(P.mark_obtained) > 120
GO
DROP TABLE dbo.Performance;
DROP TABLE dbo.Subject;
DROP TABLE dbo.Student;
Это гораздо лучший метод, чем использованиеCURSOR
.SQL Server выделяет методы, основанные на множестве, а не итеративные, и Курсор падает в последнем.
db <> fiddle