这个问题的样本数据是:
人:
人员ID | 姓名 |
---|---|
P001 | 爱丽丝 |
P002 | 鲍勃 |
P003 | 卡洛斯 |
P004 | 大卫 |
课程:
课程ID | 课程 |
---|---|
C001 | 代数 |
C002 | 生物学 |
C003 | 化学 |
出席:
课程ID | 人员ID |
---|---|
C001 | P001 |
C001 | P002 |
C001 | P003 |
C002 | P002 |
C002 | P003 |
C003 | P003 |
以下查询:
SELECT Courses.CourseID, Courses.Course, People.PersonID, People.Name
FROM Courses
INNER JOIN Attendance ON Courses.CourseID = Attendance.CourseID
INNER JOIN People ON Attendance.PersonID = People.PersonID
给我一份按课程划分的出勤列表:
C001,Algebra,P001,Alice
C001,Algebra,P002,Bob
C001,Algebra,P003,Carlos
C002,Biology,P002,Bob
C002,Biology,P003,Carlos
C003,Chemistry,P003,Carlos
现在我正在尝试获得类似但相反的结果 - 即未参加每门课程的人员列表,应如下所示:
预期结果:
C001,Algebra,P004,David
C002,Biology,P001,Alice
C002,Biology,P004,David
C003,Chemistry,P001,Alice
C003,Chemistry,P001,Bob
C003,Chemistry,P004,David
我希望我可以使用类似的东西:
SELECT Courses.CourseID, Courses.Course, People.PersonID, People.Name
FROM Courses
CROSS JOIN People
WHERE People.PersonID IN (
SELECT Attendance.PersonID
FROM Courses
INNER JOIN Attendance ON Attendance.CourseID = Courses.CourseID
)
但不幸的是,返回:
C001,Algebra,P001,Alice
C001,Algebra,P002,Bob
C001,Algebra,P003,Carlos
C002,Biology,P001,Alice
C002,Biology,P002,Bob
C002,Biology,P003,Carlos
C003,Chemistry,P001,Alice
C003,Chemistry,P002,Bob
C003,Chemistry,P003,Carlos
这表明子查询对所有课程执行一次,而不是对每个课程单独执行一次。
重要:
我正在使用的应用程序 (Claris FileMaker) 实现了 SQL-92 标准的一个非常有限的子集(并且没有很好地记录)。我只能使用带有少数子句的 SELECT 语句,并且 AFAICT 只允许 INNER JOIN、LEFT OUTER JOIN 和 CROSS JOIN。另外,除了 WHERE 子句之外,我无法在任何地方实现子查询。
是否可以仅使用简单的基本 SQL 返回预期结果?
这样的东西应该有效
select *
from Courses as c cross join People as p
left outer join Attendance as a
on (c.CourseID = a.CourseID and p.PersonID = a.PersonID)
where a.AttendId is null