尝试从SQL请求获取表

时间:2019-03-05 18:24:05

标签: sql oracle sqlplus

我现在正在一个项目上,我需要通过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

Gordon Linoff 提出的解决方案看起来非常好,除了它没有返回任何表格,因为使用以下代码,它需要包含4个课程和2个sessionCode。这里的问题是,它需要同时验证条件并附加结果。假设会话12004的条件为空,那么我可以将其视为NULL。然后,第二个条件(会话32003)给了我一个匹配。它应该同时附上两个结果,以便为我提供表格。

我只想为此请求一个。

非常感谢!

编辑:重新编写

EDIT2 :举一个已知匹配的例子

EDIT3 :进一步解释为何建议的解决方案不起作用

3 个答案:

答案 0 :(得分:1)

请考虑:group byhaving。更重要的是,请考虑JOINJOINJOIN从不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

答案 1 :(得分:0)

使用现代联接

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

答案 2 :(得分:0)

您似乎想列出在32003年任教过INF1130和INF1110的任何一位教授;或在12004年教过INF3180和INF2110。不幸的是,您提出了AND(即他们必须教授全部四门课程-一门课程和另一门课程),而不是OR(一组课程或另一门课程)。

作为扩展我认为想要的东西的漫长方式:

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值,则可以通过将其添加到group-by子句中来修改戈登的答案以计算每个sigle的匹配数:

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,因为它不是有效的标识符;因为它是关键字。我认为您已经更改了真实姓名-也许是从另一种语言开始的?)< / p>