Базовая справка по SQL-запросам (не существует)

У меня есть 3 таблицы «Доктор», «Пациент» и «Визит».

Стол доктора имеет DoctorID, имя и город.

В таблице пациентов есть PatientID, имя и город.

Таблица посещений имеет DoctorID, PatientID, NumVisits.

Я пытаюсь найти всех врачей, которых не посещал пациент из определенного города (скажем, в Нью-Йорке).

Я очень новичок в написании запросов, и я не могу заставить его работать.

Мой КОД:

SELECT DoctorId,
   Doctor.Name
FROM Visit
JOIN Doctor using(DoctorID)
JOIN Patient using(PatientID)
WHERE NOT EXISTS
    (SELECT DoctorId,
            Doctor.Name
     FROM Visit
     JOIN Doctor using(DoctorID)
     JOIN Patient using(PatientID)
     WHERE Patient.City = 'New York');

Может кто-нибудь объяснить мне, что я делаю неправильно? Может быть, весь мой подход неверен.


person nishantvodoo    schedule 15.09.2015    source источник
comment
Вам определенно не нужно 6 запросов, чтобы выполнить это! Было бы полезно сделать шаг назад и подумать об этом с другой точки зрения, хорошее эмпирическое правило заключается в том, что вы должны never выполнять больше объединений, чем таблиц, участвующих в вашем запросе!!!   -  person DanHabib    schedule 15.09.2015


Ответы (3)


Вы должны связать свой подзапрос с основным запросом. Прямо сейчас в вашем подзапросе вы выбираете всех врачей из Нью-Йорка, и, конечно же, у вас есть хотя бы один. Вот почему WHERE NOT EXISTS (1 or more rows) никогда не будет правдой. Попробуйте что-нибудь вроде этого

SELECT DoctorId,
   Doctor.Name
FROM Visit
JOIN Doctor using(DoctorID)
JOIN Patient using(PatientID)
WHERE NOT EXISTS
    (SELECT *
     FROM Visit
     JOIN Patient using(PatientID)
     WHERE Patient.City = 'New York')
     and Visit.Doctorid=Doctor.DoctorID -- Doctor.DoctorID from main query
;

И (спасибо @Brad): поскольку Patient не используется во внешнем запросе, вы можете удалить первое JOIN для Patient и Visit. На самом деле вам СЛЕДУЕТ удалить соединение с Patient и Visit во внешнем запросе, иначе вы пропустите записи для врачей, у которых нет пациентов. Результат будет

SELECT DoctorId,
   Doctor.Name
FROM Doctor 
WHERE NOT EXISTS
    (SELECT *
     FROM Visit
     JOIN Patient using(PatientID)
     WHERE Patient.City = 'New York')
     and Visit.Doctorid=Doctor.DoctorID -- Doctor.DoctorID from main query
;
person Viktor Bardakov    schedule 15.09.2015
comment
Поскольку Patient не используется во внешнем запросе, вы можете удалить первый JOIN вместо Patient и Visit. На самом деле вам СЛЕДУЕТ удалить соединение с Patient и Visit во внешнем запросе, иначе вы пропустите записи для врачей, у которых нет пациентов. - person Brad; 15.09.2015
comment
Спасибо @Брэд! Не думал об этом - person Viktor Bardakov; 15.09.2015

SELECT DISTINCT D.DOCTORID
FROM Visit V
       INNER JOIN PATIENT P ON P.PATIENTID = V.PATIENTID AND P.CITY='NEWYORK'
       RIGHT JOIN DOCTOR D ON D.DOCTORID = V.DOCTORID
WHERE P.PATIENTID IS NULL

Скрипка здесь: http://sqlfiddle.com/#!3/0e194/1

person Sateesh Pagolu    schedule 15.09.2015

вы можете сделать это следующим образом:

SELECT DoctorId, Doctor.Name
From Doctor 
Where DoctorId NOT IN (Select DoctorId From Visit
                       Where  PatientID IN (Select  PatientID From Patient 
                                                Where  City = 'New York'))

Таким образом, вы выбираете пациентов из указанного города в самой внутренней выборке, затем вы берете DoctorId, где посещали эти пациенты, и, наконец, выбираете врачей, которых нет среди них.

person Mahmoud    schedule 15.09.2015