Попытка получить таблицу из SQL-запроса - PullRequest
0 голосов
/ 05 марта 2019

Я сейчас работаю над проектом, и мне нужно сделать запрос к моей БД через SQL * PLUS.

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

  • (Первый) Всеанс (скажем, 12004), профессор действительно преподавал эти два курса, INF3180 и INF2110

  • (Второй) В другой сессии, 32003Профессор действительно преподавал эти два курса: INF1130 и INF1110

Вот код, который создал БД:

CREATE TABLE Professor
(professorCode  CHAR(5) NOT NULL,
 lastName           VARCHAR(10) NOT NULL,
 firstName      VARCHAR(10) NOT NULL,
 CONSTRAINT PrimaryKeyProfessor PRIMARY KEY     (professorCode)
)
;

CREATE TABLE Group
(sigle      CHAR(7)     NOT NULL,
 noGroup    INTEGER     NOT NULL,
 sessionCode INTEGER        NOT NULL,
 maxInscriptions    INTEGER     NOT NULL,
 professorCode  CHAR(5) NOT NULL,
CONSTRAINT PrimaryKeyGroup PRIMARY KEY   
(sigle,noGroupe,sessionCode),
CONSTRAINT CESigleGroupeRefCours FOREIGN KEY    (sigle) REFERENCES Cours,
CONSTRAINT CECodeSessionRefSession FOREIGN KEY  (sessionCode) REFERENCES 
Session,
CONSTRAINT CEcodeProfRefProfessor FOREIGN KEY(professorCode) REFERENCES 
Professor
) 
;

А вот мой текущий неработающий запрос:

SELECT DISTINCT Professor.firstName, Professor.lastName
FROM            Professor, Group
WHERE           Group.professorCode = Professor.professorCode
                AND Group.sessionCode = 32003
                AND (Group.sigle = 'INF1130' AND
                     Group.sigle = 'INF1110')
                OR Group.sessionCode = 12004 
                AND (Group.sigle = 'INF3180' AND
                     Group.sigle = 'INF2110')

Я знаю, что есть способ объединить оба результата, но я не могу его найти.

В этом случае возможно только одно совпадение :

  • Только одно совпадение с 32003: INF1130, INF1110
  • Нет совпадения с 12004: INF3180, INF2110

Полученная таблица должна выглядеть следующим образом:

--------------------------
First Name       Last Name
--------------------------
Denis            Tremblay

Предлагаемое решение, данное Гордоном Линоффом , выглядит какочень хорошо, за исключением того, что он не возвращает мне таблицы, так как для следующего кода необходимо включить 4 курса и 2 sessionCode.Проблема здесь в том, что необходимо проверить оба условия и добавить результат.Допустим, условия для сеанса 12004 ни к чему не приводят, тогда я могу считать его NULL.Затем второе условие с сеансом 32003 дает мне одно совпадение.К этому результату следует добавить оба результата, чтобы получить таблицу, представленную поверх.

Я хочу сделать один запрос только для этого.

Спасибо МНОГО!

РЕДАКТИРОВАТЬ : переформулировано

EDIT2 : приведен пример известного совпадения

EDIT3 : дальнейшее объяснение, почему предлагаемое решение не работает

Ответы [ 3 ]

1 голос
/ 05 марта 2019

Подумайте: group by и having. Что еще более важно, подумайте JOIN, JOIN, JOIN. Никогда не используйте запятые в предложении from.

SELECT p.firstName, p.lastName
FROM Professor p JOIN
     Group g
     ON g.professorCode = p.professorCode
WHERE (g.sessionCode, g.sigle) IN ( (32003, 'INF1130'), (32003, 'INF1110'),
                                    (12004, 'INF3180'), (12004, 'INF2110')
                                  )
GROUP BY p.firstName, p.lastName
HAVING COUNT(DISTINCT g.sigl) = 4;  -- has all four
0 голосов
/ 05 марта 2019

Похоже, вы хотите перечислить любого профессора, который или преподавал INF1130 и INF1110 в 32003;или преподавал INF3180 и INF2110 в 12004. К сожалению, вы представили это как И (то есть они должны были преподавать все четыре курса - одна пара курсов И другой), а не ИЛИ (один набор курсов ИЛИ другой).

Как многословный способ расширить то, что, я думаю, вы хотите:

SELECT p.firstName, p.lastName
FROM Professor p
WHERE (
  EXISTS (
    SELECT *
    FROM GroupX g
    WHERE professorCode = p.professorCode
    AND sessionCode = 32003
    AND sigle = 'INF1130'
  )
  AND EXISTS (
    SELECT *
    FROM GroupX g
    WHERE professorCode = p.professorCode
    AND sessionCode = 32003
    AND sigle = 'INF1110'
  )
)
OR (
  EXISTS (
    SELECT *
    FROM GroupX g
    WHERE professorCode = p.professorCode
    AND sessionCode = 12004
    AND sigle = 'INF3180'
  )
  AND EXISTS (
    SELECT *
    FROM GroupX g
    WHERE professorCode = p.professorCode
    AND sessionCode = 12004
    AND sigle = 'INF2110'
  )
);

Четыре подзапроса не будут ужасно эффективными.Вместо этого вы могли бы выполнять множественные объединения.

Если вы всегда будете искать два sigle значения для sessionCode, тогда вы можете изменить ответ Гордона, чтобы подсчитать, сколько совпадений соответствует каждому sigle, добавив его кпредложение group-by:

SELECT p.firstName, p.lastName
FROM GroupX g
JOIN Professor p
ON p.professorCode = g.professorCode
WHERE (g.sessionCode, g.sigle) IN ( (32003, 'INF1130'), (32003, 'INF1110'),
                                    (12004, 'INF3180'), (12004, 'INF2110')
                                  )
GROUP BY p.firstName, p.lastName, g.sessionCode
HAVING COUNT(*) = 2;

Если бы у вас был профессор, который преподавал все четыре, вы бы перечислили их дважды;если это может произойти, вы можете добавить свой DISTINCT обратно, хотя это немного не так.Вы также можете использовать подзапрос и IN, чтобы избежать этого:

SELECT p.firstName, p.lastName
FROM Professor p
WHERE ProfessorCode IN (
  SELECT professorCode
  FROM GroupX
  WHERE (sessionCode, sigle) IN ( (32003, 'INF1130'), (32003, 'INF1110'),
                                  (12004, 'INF3180'), (12004, 'INF2110')
                                )
  GROUP BY professorCode, sessionCode
  HAVING COUNT(*) = 2
)

(я изменил Group на GroupX, потому что это недопустимый идентификатор; потому что это ключевое слово. IПредположим, вы изменили свои настоящие имена - может быть, с другого языка?)

0 голосов
/ 05 марта 2019

использовать современное соединение

SELECT Professor.firstName, Professor.lastName
FROM            Professor join "Group" g on
            g.professorCode = Professor.professorCode
               where  g.sessionCode in( 32003,12004 )
                AND g.sigle in( 'INF1130', 'INF1110','INF3180','INF2110')                        
             group by  Professor.firstName, Professor.lastName
             having count( distinct sigle )=4
...