SQL:连接多个表
Posted
技术标签:
【中文标题】SQL:连接多个表【英文标题】:SQL : join more than one table 【发布时间】:2020-10-11 06:11:51 【问题描述】:编写一个 sql 查询来选择参加过“JOHN”教授的所有讲座但没有参加过“JOSEPH”教授的任何讲座的学生的姓名。
我已经写了这个查询,但它给了我正在听约瑟夫讲课的学生的名字。
select distinct s.studentname
from Student s,Attendance a,Lecture l
where s.StudentId=a.studid
and l.lecId = a.lectureid
and l.professor='JOHN'
and l.professor != 'JOSEPH';
我在上述查询中犯了一些错误,但无法识别。
这是表结构
学生桌
# StudentId, StudentName, Sex
'1', 'AMY', 'M'
'2', 'JACK', 'M'
'3', 'TONY', 'M'
'4', 'TARA', 'M'
'5', 'SARAH', 'F'
'6', 'TOM', 'F'
讲台
# LecId, Subject, Professor
1, MATH, JOHN
2, MATH, JOSEPH
3, PHY, MARK
4, PHY, MAX
5, PHY, JOHN
6, CHEM, JOHN
7, CHEM, JOSEPH
8, HISTORY, JOSEPH
考勤表
# StudId, LectureId
'1', '1'
'1', '2'
'3', '1'
'2', '5'
'2', '6'
'3', '4'
'1', '6'
'4', '5'
'5', '1'
'5', '2'
'1', '3'
'1', '4'
'1', '5'
'1', '6'
【问题讨论】:
请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。 您使用的连接语法在 1992 年的标准 SQL 中变得多余。那是在 mysql 发明之前!如果您正在上课或使用一本书或教程教您使用这种古老的语法,您应该退出它。请改用正确的显式连接(INNER JOIN
、LEFT OUTER JOIN
等)。
【参考方案1】:
您需要查看属于给定学生的所有行,因此简单的where
子句无法满足您的要求。相反,您可以使用带有 having
子句的聚合和文件管理器:
select s.studentname
from student s
inner join attendance a on s.studentId = a.studid
inner join lecture l on l.lecId = a.lectureid
group by s.studentId, s.studentname
having max(l.professor= 'JOHN') = 1 and max(l.professor = 'JOSEPH') = 0
如果您希望教师添加所有约翰的讲座,而不是约瑟夫的讲座,那么:
select s.studentname
from student s
inner join attendance a on s.studentId = a.studid
inner join lecture l on l.lecId = a.lectureid
group by s.studentId, s.studentname
having
sum(l.professor= 'JOHN') = (select count(*) from lecture where professor = 'JOHN')
and max(l.professor = 'JOSEPH') = 0
【讨论】:
嘿,抱歉,对问题做了一点改动,这将产生很大的影响.. 非常抱歉,您现在能帮帮我吗:)【参考方案2】:如果你的 MySQL 版本支持 GROUP_CONCAT,你可以试试下面的脚本-
Demo Here
SELECT S.StudentId,S.StudentName, GROUP_CONCAT(DISTINCT L.Professor)
FROM Attendance A
INNER JOIN Lecture L ON A.LectureId = L.LecId
INNER JOIN Student S ON A.StudId = S.StudentId
GROUP BY S.StudentId,S.StudentName
HAVING GROUP_CONCAT(DISTINCT L.Professor) = 'JOHN'
以上查询将返回仅从“JOHN”学习课程的学生列表。没有其他人。
但如果您的要求更改为在列表中添加更多教授,您可以在 HAVING 子句检查中相应地添加教授名称。但是您需要在这种情况下应用适当的排序。
【讨论】:
接近了,但为什么它没有给出 JACK 的名字,学生:2,他也只参加了 JOHN 是的,应该有 2 个,检查中 更改了一点@sparsh610 请检查【参考方案3】:试试:
select * from Student st
where exists(select * from Lecture l
join Attendance a
on l.LecId = a.LectureId
where l.Professor = 'John'
and a.StudId = st.StudentId)
and exists(select * from Lecture l
join Attendance a
on l.LecId = a.LectureId
where l.Professor = 'Joseph'
and a.StudId = st.StudentId)
【讨论】:
@sparsh610 能否请您添加 DDL 以便我进行测试?此外,托尼也满足要求。你目前的结果是什么? 如何在 mysql 中获取? 只需将数据放入sqlfiddle.com并分享链接 嘿,抱歉,对问题做了一点改动,这将产生很大的影响.. 非常抱歉,您现在能帮帮我吗:) @sparsh610 立即尝试。【参考方案4】:select s.StudentName
from Student s
inner join Attendance a on s.StudentId = a.StudId
inner join Lecture l on l.LecId = a.LectureId
group by s.StudentId, s.StudentName
having
sum(l.Professor= 'JOHN') = (select count(*) from lecture where Professor = 'JOHN')
and max(l.Professor = 'JOSEPH') = 0
order by s.StudentName
#asked in interview (MakeMyTrip)
【讨论】:
感谢您添加到答案列表中。虽然有些人可能能够立即了解您分享的内容,但其他人可能不会。除了代码之外,至少添加一点上下文会更有帮助。【参考方案5】:我重新表述了你所做的加入...但它似乎有效。
此查询是否返回您要查找的数据集?
SELECT s.studentname, l.Subject, l.Professor
FROM Student s JOIN Attendance a
ON s.StudentId = a.StudId
JOIN Lecture l
ON l.lecId = a.lectureid
WHERE l.professor='JOHN'
AND l.professor != 'JOSEPH';
【讨论】:
【参考方案6】:MSSQL:
WITH cte AS
(
SELECT StudentName, ROW_NUMBER()
OVER(
PARTITION BY studid
ORDER BY studid
) cou
FROM attendance a,lecture l,student s
WHERE a.LectureId = l.LecId
AND a.StudId = s.StudentId
AND l.Professor = 'john'
)
SELECT StudentName
FROM cte
WHERE cou = 3
Except
SELECT StudentName
FROM attendance a, lecture l, student s
WHERE a.LectureId = l.LecId
AND a.StudId = s.StudentId
AND l.Professor = 'joseph'
【讨论】:
我在 studid 上使用 partitionby 并获取参加了所有 john 三个班级的学生(where 子句的条件)。我使用 cou=3 来抓取参加了 john 的所有 3 个班级的学生。在下一步中,我将在学生使用 cte 表参加 joseph 课程的桌子上使用 except。在这里我得到了想要的输出,表 a 排除了表 b 中存在的标准名称。以上是关于SQL:连接多个表的主要内容,如果未能解决你的问题,请参考以下文章