这来自斯坦福Coursera自学DB课程SQL测验:
你家乡高中的学生决定组织他们的 社交网络使用数据库。到目前为止,他们收集了 有关十六名学生的信息,分为四个等级,9-12。这是 架构:
Highschooler (ID, name, grade)
英语:有一个高中生有唯一的ID和给定的 某个年级的名字。
Friend (ID1, ID2)
英语:ID1的学生是ID2学生的朋友。 友谊是相互的,所以如果(123,456)在朋友表中,那么也是如此 (456,123)。
Likes (ID1, ID2)
英语:ID1的学生喜欢ID2的学生。喜欢 某人不一定是相互的,所以如果(123,456)在喜欢中 表,不保证(456,123)也存在。
数据库 here
提示:对于每个学生A喜欢学生B,两个人不是朋友,找出他们是否有一个共同的朋友C(谁可以介绍 他们!)。对于所有这些三重奏,请返回A,B和C的名称和等级。
我有一个生成正确结果的查询,以及一个生成错误结果的查询,但我无法从逻辑上弄清楚为什么以下查询不正确。我已经加粗了引起问题的问题,但我很难通过思考并希望进行简短的代码审查。
由于条款and b.id not in (select id2 from friend where a.id=id1)
而导致的工作查询:
select distinct a.name, a.grade, b.name, b.grade, c.name, c.grade
from highschooler a, highschooler b, highschooler c, likes, friend
where a.id=likes.id1
and b.id=likes.id2
and a.id=friend.id1
-- this next line
and b.id not in (select id2 from friend where a.id=id1)
and b.id in (select id1 from friend where id2=c.id)
and a.id in (select id1 from friend where id2=c.id)
由于条款and b.id <>friend.id2
而导致查询不正确:
select distinct a.name, a.grade, b.name, b.grade, c.name, c.grade
from highschooler a, highschooler b, highschooler c, likes, friend
where a.id=likes.id1
and b.id=likes.id2
and a.id=friend.id1
-- as opposed to this one
and b.id <>friend.id2
and b.id in (select id1 from friend where id2=c.id)
and a.id in (select id1 from friend where id2=c.id)
查询1结果:
Andrew 10 Cassandra 9 Gabriel 9
Austin 11 Jordan 12 Andrew 10
Austin 11 Jordan 12 Kyle 12
查询2结果:
Andrew 10 Cassandra 9 Gabriel 9
Brittany 10 Kris 10 Haley 10
Austin 11 Jordan 12 Andrew 10
Austin 11 Jordan 12 Kyle 12
Gabriel 11 Alexis 11 Jessica 11
答案 0 :(得分:2)
这两个条件具有非常不同的含义:
--1 and b.id not in (select id2 from friend where a.id=id1) --2 and b.id <> friend.id2
假设b.id
为jack
,select id2 from friend where a.id=id1
为:
id2
---
alice
bob
在第一个查询中,对于表jack
中的b
行,您实际上有条件“jack不是(alice,bob)之一”。这产生了真,因此该行将包含在输出中。
在第二个查询中,对于表jack
中的b
行,您实际上是在尝试加入friend
表id2
不在jack
{1}}。在我们的示例中,有2条此类记录,一条记录为alice
,另一条记录为bob
。因此,在输出中,您将获得jack
的2条记录,一条用于alice
,另一条用于bob
。
在第一个查询中,您或者从jack
获取b
的记录。在第二个查询中,您获得n
的{{1}}条记录,其中jack
是n
不是id2
的记录数。如果所有记录都是jack
,那么您将不会从jack
获得任何记录。完全不同的东西。
答案 1 :(得分:-1)
您的问题似乎主要来自于使用ANSI-89 join
而不是使用现代显式join
。如果您使用了现代join
s,则可以更轻松地进行故障排除。
您的第一个版本正在制作现在称为inner join
的版本,而您的第二个版本正在寻找&#34;不等于&#34;。这就是你得到不同结果的原因。