2014-09-26 2 views
3

Это добыта из самообучения класса DB SQL викторинах Stanford Coursera:разницы между социальной сетью запросами

Студентов в вашем родном городе средней школы решили организовать их социальной сети с использованием баз данных. До сих пор они собрали информацию о шестнадцати учениках в четырех классах, 9-12. Вот схема:

Highschooler (ID, name, grade) 

Английский: Существует старшеклассник с уникальным идентификатором и заданной имени в определенном классе.

Friend (ID1, ID2) 

English: Студент с ID1 дружит со студентом с ID2. Дружба взаимная, поэтому, если (123, 456) находится в таблице друзей, то есть (456, 123).

Likes (ID1, ID2) 

English: Студент с ID1 любит студента с ID2. Liking кто-то не обязательно взаимно, поэтому, если (123, 456) находится в таблице Likes , нет никакой гарантии, что (456, 123) также присутствует.

Database here

Подсказка: Для каждого студента, который любит студенческую 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 Габриэля 9

Austin 11 Jordan 12 Andrew 10

Остин 11 Иордания 12 Kyle 12

Запрос 2 результат:

Andrew 10 Cassandra 9 Gabriel 9

Бретань 10 Kris 10 Haley 10

Austin 11 Jordan 12 Andrew 10

Austin 11 Jordan 12 Kyle 12

Gabriel 11 Alexis 11 Jessica 11

+0

Пожалуйста, добавьте исходные записи для каждой таблицы или настройте http://sqlfiddle.com. Я попытался найти базу данных по URL-адресу, но я не пройду он-лайн курс, чтобы получить его. –

ответ

2

Эти 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, b О.Б.)». Что дает true, поэтому строка будет включена в выход.

Во втором запросе, для ряда jack в таблице b, вы эффективно пытаетесь присоединиться к friend столу, где id2 не jack. В нашем примере есть 2 таких записи, одна с alice и одна с bob. Таким образом, на выходе вы получите 2 записи для jack, один для alice и один для bob.

В первом запросе вы либо получаете запись с jack от b, либо нет. Во втором запросе вы получите n записей для jack, где n - количество записей, в которых id2 не является jack.Если все записи jack, то вы не получите никаких записей от b. Совершенно разные вещи.

+0

Ваше объяснение имеет смысл (n записей для jack vs 1 record), но я все еще неясен, почему Бриттани появлялась по одному запросу, но не по другому. Для ясности я добавил результаты обоих запросов к моему вопросу. – jfalkson

+0

, потому что запись Бретани удовлетворяет условию 'b.id <> friend.id2' – janos

+0

, но разве это не значит, что крис не должен дружить с бриттани (так как идентификатор Бриттани не является одним из идентификаторов (id2) друга Криса)? – jfalkson

-1

Ваши проблемы, похоже, в основном связаны с использованием ANSI-89 join s вместо использования современных явных join. Если вы использовали современные join s, было бы намного проще устранить неполадки.

Ваша первая версия делает то, что теперь известно как inner join, в то время как ваша вторая версия ищет «не равную». Вот почему вы получаете разные результаты.

Смежные вопросы