想象一下以下数据集。 (这不是我正在研究的完全相同的问题,但这只是一个演示需求的简单示例)
Student ID, Course ID
S1 C1
S1 C2
S1 C3
S2 C1
S2 C3
S3 C1
S3 C2
在以上数据集中,每个学生的课程号都被注册了。我想找出导致此表中所有原因的学生。
因此,如果我使用INTERSECT关键字,它将看起来像这样。
SELECT student_id FROM <table> where course_id = 'C1'
INTERSECT
SELECT student_id FROM <table> where course_id = 'C2'
INTERSECT
SELECT student_id FROM <table> where course_id = 'C3'
显然,只有在课程列表固定的情况下,此功能才起作用。
有没有办法做到这一点,因为课程列表是动态的并且仅使用SQL。
我可以编写一个PLSQL函数来做到这一点。但是随后将为每个唯一的课程ID执行一个游标,并且交集将由PLSQL代码完成。
我正在寻找是否有可能将尽可能多的数据卸载到SQL引擎(可能正在使用分析函数),因为涉及的数据集可能很大。
答案 0 :(得分:4)
尝试这样的事情:
SELECT student_id FROM <table>
WHERE course_id IN (SELECT course_id FROM <anothertable>)
GROUP BY student_id
HAVING COUNT(DISTINCT course_id)=(SELECT COUNT(DISTINCT course_id) FROM <anothertable>)
这样,您可以确保为student_id
中指定的每个course_id
注册每个返回的<anothertable>
。
这称为“关系部门”,另请参见https://www.red-gate.com/simple-talk/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/
编辑(作者戈登):
在该问题中仅提及一个表,因此查询为:
SELECT student_id
FROM t
GROUP BY student_id
HAVING COUNT(DISTINCT course_id) = (SELECT COUNT(DISTINCT course_id) FROM t)
答案 1 :(得分:3)
Oracle允许您使用COUNT(DISTINCT)
作为分析功能。
因此,您可以这样做:
SELECT DISTINCT student_id
FROM (SELECT student_id,
COUNT(DISTINCT course_id)
OVER ( PARTITION BY student_id ) AS course_per_student,
COUNT(DISTINCT course_id) OVER () AS available_courses
FROM t)
WHERE course_per_student = available_courses