Oracle SQL Есть ли способ найти пересечения наборов данных, хранящихся в одной таблице, когда число наборов данных является динамическим - PullRequest
2 голосов
/ 04 июля 2019

Представьте себе следующий набор данных.(Это не та же самая проблема, над которой я работаю, но это просто простой пример, который демонстрирует требование)

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 для этого.Но тогда для каждого уникального идентификатора курса будет выполняться курсор, а пересечение будет выполняться с помощью кода PLSQL.

Я смотрю, возможно ли разгрузить как можно большую часть в движок SQL (возможно, с использованием аналитических функций), так как набор данных может быть большим.

Ответы [ 2 ]

4 голосов
/ 04 июля 2019

Попробуйте что-то вроде этого:

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-программирование / разделение-мы-стой-sql-из-реляционного деления /

РЕДАКТИРОВАТЬ (Гордон):

В вопросе упоминается только одна таблица, поэтому запрос:

SELECT student_id
FROM t
GROUP BY student_id 
HAVING COUNT(DISTINCT course_id) = (SELECT COUNT(DISTINCT course_id) FROM t)
3 голосов
/ 04 июля 2019

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 

DEMO

...