我正在使用SQL Developer中的一个简单的SQL查询,我似乎无法正确使用这个查询。我的查询是:"检索所有所有约会的导师的姓名,其中的地址是''"
这是我的SQL:
SELECT Appt.TUTOR_USER_ID, TUTORS.FIRST_NAME, TUTORS.LAST_NAME
FROM Appt,
(
SELECT Tutor.USER_ID, USR.FIRST_NAME, USR.LAST_NAME
FROM Tutor, "USER" USR
WHERE Tutor.USER_ID = USR.ID
) TUTORS,
(
SELECT USR.ID, USR.FIRST_NAME, USR.LAST_NAME
FROM Student, "USER" USR
WHERE Student.USER_ID = USR.ID
) USERS
WHERE (Appt.TUTOR_USER_ID = TUTORS.USER_ID AND Appt.STUDENT_USER_ID = USERS.ID)
AND (USERS.FIRST_NAME = 'John' AND USERS.LAST_NAME = 'Smith');
这给了我的是所有与约翰史密斯约会的导师,但并非所有他们与约翰史密斯的约会。因此,除了约翰史密斯之外,我还得到了与其他人约会的导师。任何人都可以在这里给我一个正确的陈述或逻辑。
答案 0 :(得分:2)
您只查找与该名称匹配的记录,因此目前无需计算或排除任何其他内容。你可以添加一个and not exists
条款来查询其他学生;或者因为它在你的问题标题中,minus
也是如此:
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join tutor t on t.user_id = a.tutor_user_id
join student s on s.user_id = a.student_user_id
join "USER" tu on tu.id = t.user_id
join "USER" su on su.id = s.user_id
where su.first_name = 'John' and su.last_name = 'Smith'
minus
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join tutor t on t.user_id = a.tutor_user_id
join student s on s.user_id = a.student_user_id
join "USER" tu on tu.id = t.user_id
join "USER" su on su.id = s.user_id
where not (su.first_name = 'John' and su.last_name = 'Smith');
但是,我使用group by
和having
条款来计算John Smith和其他任何人的约会数量:
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join tutor t on t.user_id = a.tutor_user_id
join student s on s.user_id = a.student_user_id
join "USER" tu on tu.id = t.user_id
join "USER" su on su.id = s.user_id
group by a.tutor_user_id, tu.first_name, tu.last_name
having count(case when su.first_name = 'John' and su.last_name = 'Smith'
then 1 else null end) > 0
and count(case when su.first_name = 'John' and su.last_name = 'Smith'
then null else 1 end) = 0;
SQL Fiddle demo包含一些简单数据,原始查询(也显示重复数据)以及这两个版本。
正如JosephB和Serpiton所提到的,我忘了说,你实际上并不需要通过tutor
或student
表,因为他们并没有真正添加任何东西;您可以直接从"USER"
列加入appt
表:
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join "USER" tu on tu.id = a.tutor_user_id
join "USER" su on su.id = a.student_user_id
group by a.tutor_user_id, tu.first_name, tu.last_name
having count(case when su.first_name = 'John' and su.last_name = 'Smith'
then 1 else null end) > 0
and count(case when su.first_name = 'John' and su.last_name = 'Smith'
then null else 1 end) = 0;
在这两种情况下,我都重写了原始版本以使用ANSI join
语法而不是旧的Oracle样式,并在我在那里时删除了子查询,因为所有连接都可以在一个级别上完成。不过,我强烈建议您重新考虑您的表名,这样您就不必使用带引号的标识符;也许可以称他们为users
,tutors
和students
?
答案 1 :(得分:2)
另一种方法是首先过滤约会以获得导师只看到学生的约会,并将其用作主要查询的基础
WITH tutor_appt As (
SELECT tutor_user_id
, MAX(student_user_id) student_user_id
FROM appt
GROUP BY tutor_user_id
HAVING COUNT(DISTINCT student_user_id) = 1
)
SELECT a.tutor_user_id, tu.first_name, tu.last_name
FROM tutor_appt a
INNER JOIN "USER" tu on tu.id = a.tutor_user_id
INNER JOIN "USER" su on su.id = a.student_user_id
where su.first_name = 'John' and su.last_name = 'Smith';
如果数据库是理智的,则在加入Tutor
之前无需将Student
和appt
表加入USER
:tutor_user_id
和{ {1}}列可以直接加入student_user_id
。
答案 2 :(得分:0)
这是绕过TUTORS和STUDENTS表的替代方法,因为Appt.TUTOR_USER_ID
和Appt.STUDENT_USER_ID
都应该以{{1}}的形式存在。
"USER".ID
导师'名称是通过加入USER表获得的。然后,Appt表再次与USER表连接,以过滤给定学生的姓名。
请参阅 SQL Fiddle 演示。