子查询应用困惑:求解正确查询选修Comp. Sci.课程学生的SQL语句
问题分析与错误修正
需求:找出至少选修过一门Comp. Sci.课程的学生的ID和姓名,结果中无重复姓名。
错误语句1分析
SELECT DISTINCT `ID`,`name` FROM `student` WHERE dept_name >= 'comp.sci.'
- 逻辑完全偏离:需求是找选修过Comp. Sci.课程的学生,不是找所在系为Comp. Sci.的学生,用
student表的dept_name筛选根本无法关联选课信息。 - 运算符误用:字符串比较用
>=毫无意义,即便要筛选系,也应该用=而不是范围运算符。 - 未关联选课表:学生的选课记录存在
takes表(需关联course表获取课程所属系),不关联就无法判断学生是否选了目标课程。
错误语句2分析
SELECT DISTINCT `ID`, name, dept_name FROM `student` WHERE dept_name > SOME IN (SELECT ID, name, dept_name FROM student WHERE dept_name = 'comp.sci.')
- 语法错误:
SOME与IN不能连用,正确用法是SOME(子查询)。 - 子查询字段不匹配:外层用
dept_name比较,但子查询返回了3个字段,SOME要求子查询返回单个字段才能进行比较。 - 逻辑偏离:依旧在围绕学生的系做文章,完全没涉及“选修课程”的判断,且
>的比较逻辑对需求毫无意义。 - 多余字段:需求只需要ID和姓名,这里多查了
dept_name字段。
错误语句3分析
SELECT DISTINCT S.`ID` S.`name` FROM student JOIN takes T on T.ID= S.ID WHERE dept_name IN (SELECT ID, name FROM takes WHERE dept_name = 'comp.sci.')
- 语法错误:
S.ID和`S.`name之间缺少逗号,会导致SQL解析失败。 - 字段歧义:
WHERE中的dept_name未指定表,student和takes(或关联的course)都可能有该字段,数据库无法确定要引用哪个表的字段。 - 子查询错误:
IN要求子查询返回单个字段,但这里返回了ID和name两个字段,语法不合法;且子查询逻辑错误,应该筛选的是所属系为Comp. Sci.的课程的选课记录,而不是takes表的dept_name(通常takes表没有dept_name,课程的系在course表)。
正确写法示例
方式1:关联表查询
SELECT DISTINCT S.ID, S.name FROM student S JOIN takes T ON S.ID = T.ID JOIN course C ON T.course_id = C.course_id WHERE C.dept_name = 'Comp. Sci.'
方式2:子查询(存在性判断)
SELECT DISTINCT ID, name FROM student WHERE EXISTS ( SELECT 1 FROM takes T JOIN course C ON T.course_id = C.course_id WHERE T.ID = student.ID AND C.dept_name = 'Comp. Sci.' )
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

