Как мне переписать мой запрос, чтобы он основывался на существовании данного внешнего ключа, а не на количестве повторений этого ключа? - PullRequest
1 голос
/ 05 октября 2011

В большинстве случаев у меня есть запрос, подобный приведенному ниже:

SELECT tutor_school.name, count(*), tutor_school.schoolid 

FROM tutor_school, tutor_attends, tutor_tutors_in 

WHERE 
tutor_school.schoolid = tutor_attends.schoolid and 
tutor_school.schoolid in ('1', '2', '3') and 
tutor_attends.userid=tutor_tutors_in.userid

group by tutor_school.schoolid LIMIT 0, 10

По сути, я хочу:

Название школы, Количество учеников, посещающих ту школу, в которой учительпо любому предмету, Schoolid

На самом деле я получаю

Название школы, сумма всех предметов, преподаваемых учениками в этой школе, Schoolid - в другихсловами, если ученик 1 наставник 3 предмета, ученик 2 наставник 5, то вместо возвращения 2 я получаю 8!

Я понял, что проблема в следующем утверждении:

tutor_attends.userid=tutor_tutors_in.userid

Это не проверяет существование данного внешнего ключа в удаленной таблице, оно дает результат для каждого экземпляра этого ключа.

То, что я пытаюсь выяснить, этокак связать это, чтобы ограничить это просто существованием данного ключа, а не количеством раз, которое ключ встречается.Я знаю, что видел пример, подобный этому, в моем классе SQL, но я не могу вспомнить, какое было решение.

Ответы [ 3 ]

2 голосов
/ 05 октября 2011

Эндрю прав, и вот конкретный пример его решения (пришлось делать предположения по дизайну вашего стола):

SQL> SELECT * FROM tutor_school;

  SCHOOLID NAME
---------- --------------------
         1 School A
         2 School B
         3 School C


SQL> SELECT * FROM tutor_attends;

    USERID   SCHOOLID
---------- ----------
         1          1
         2          1
         3          2


SQL> SELECT * FROM tutor_tutors_in;

    USERID SUBJECT
---------- --------------------
         1 Math
         1 Science
         1 English
         2 English
         3 Math


SQL> SELECT tutor_school.name, COUNT(DISTINCT tutor_tutors_in.userid)
  2  FROM tutor_school, tutor_attends, tutor_tutors_in
  3  WHERE tutor_school.schoolid=tutor_attends.schoolid
  4  AND tutor_attends.userid=tutor_tutors_in.userid
  5  GROUP BY tutor_school.name
  6  /

NAME                 COUNT(DISTINCTTUTOR_TUTORS_IN.USERID)
-------------------- -------------------------------------
School A                                                 2
School B                                                 1
1 голос
/ 05 октября 2011

Во-первых, вы должны изучить синтаксис ANSI для JOIN. Использование только условия WHERE не рекомендуется. Оставляя это в стороне, я могу придумать решение, даже не используя EXISTS.

SELECT tutor_school.name, count(DISTINCT tutor_attends.userid), tutor_school.schoolid 

FROM tutor_school, tutor_attends, tutor_tutors_in 

WHERE 
tutor_school.schoolid = tutor_attends.schoolid and 
tutor_school.schoolid in ('1', '2', '3') and 
tutor_attends.userid=tutor_tutors_in.userid

group by tutor_school.schoolid LIMIT 0, 10

Меня немного смущает ваша схема: я вижу таблицы соединений, но нет старой tutor таблицы. Возможно, было бы проще концептуализировать запрос с одним.

0 голосов
/ 05 октября 2011

Требуемый вам реляционный оператор: semijoin (вместо join). Исходя из вашего требования к естественному языку, я думаю, что использование EXISTS было бы наиболее подходящим

например.

SELECT tutor_school.name, count(*), tutor_school.schoolid 
FROM tutor_school, tutor_tutors_in 
WHERE 
tutor_school.schoolid = tutor_attends.schoolid and 
tutor_school.schoolid in ('1', '2', '3') and
exists (
        SELECT *
          FROM tutor_attends
         WHERE tutor_attends.userid = tutor_tutors_in.userid
       )
group by tutor_school.schoolid LIMIT 0, 10
...