我现在正在一个项目上,我需要通过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')
我知道有一种将两种结果结合起来的方法,但是我似乎找不到。
在这种情况下,只有一场比赛:
结果表应该看起来像这样:
--------------------------
First Name Last Name
--------------------------
Denis Tremblay
由 Gordon Linoff 提出的解决方案看起来非常好,除了它没有返回任何表格,因为使用以下代码,它需要包含4个课程和2个sessionCode。这里的问题是,它需要同时验证条件并附加结果。假设会话12004的条件为空,那么我可以将其视为NULL。然后,第二个条件(会话32003)给了我一个匹配。它应该同时附上两个结果,以便为我提供表格。
我只想为此请求一个。
非常感谢!
编辑:重新编写
EDIT2 :举一个已知匹配的例子
EDIT3 :进一步解释为何建议的解决方案不起作用
答案 0 :(得分:1)
请考虑: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
答案 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>