SQL Slow вложенный запрос - PullRequest
0 голосов
/ 26 июля 2011

У меня есть стол под названием Staff и стол под надзором.

Персонал имеет StaffID, FirstName, LastName и т.д ...

Супервизоры содержат RelationshipID, StaffID, SupervisorID, SetBy, SetOn, Status.

По сути, таблицы супервизоров дают нам контрольный журнал для взаимоотношений с персоналом. У нас есть таблица персонала, и у нас есть таблица персонала: взаимоотношения с персоналом (супервизор: персонал) с некоторой дополнительной информацией (устаревшей, текущей, неправильной) и идентификатор персонала, который его установил и когда он его установил.

Теперь я пишу запрос, чтобы найти всех осиротевших сотрудников. У меня есть:

SELECT *
  FROM Staff
 WHERE StaffID NOT IN (SELECT StaffID
                         FROM Supervisors
                        WHERE Status = 0 
                           OR Status = 2);

(статус 0 - исходная загрузка из корпоративной БД, а 2 - измененная запись, которая была проверена. Все остальные «устарели», «неверны» и т. Д.) *

Проблема в том, что у меня более 6000 сотрудников и более 5000 сотрудников: отношения супервизора, и это в основном запрос NxM, означающий, что MySQL должен просеять 3 миллиона перестановок.

Я не ниндзя SQL, есть ли лучший способ сделать это?

(Обратите внимание, я не ожидаю, что этот конкретный запрос будет выполняться очень часто)

Ответы [ 2 ]

3 голосов
/ 26 июля 2011

Предполагая, что столбцы SUPERVISOR.staffid и SUPERVISOR.status равны , не могут быть обнулены , используйте:

   SELECT st.*
     FROM STAFF st
LEFT JOIN SUPERVISOR s ON s.staffid = st.staffid
                      AND s.status NOT IN (0,2)
    WHERE s.staffid IS NULL

В противном случае NOT IN / NOT EXISTS эквивалентны и работают лучше, если столбцы обнуляются.

Для получения дополнительной информации:

3 голосов
/ 26 июля 2011

Это было бы лучше выполнить как объединение, чем как NOT IN:

SELECT st.* 
FROM Staff st
LEFT JOIN Supervisors su ON st.StaffID = su.StaffID 
          AND (su.Status <> 0 AND su.Status <> 2)
WHERE su.StaffId IS NULL

Вот как я его преобразовал:

NOT IN (SELECT StaffID FROM Supervisors WHERE Status = 0 OR Status = 2)

с применением закона Буля эквивалентно

IN (SELECT StaffID FROM Supervisors WHERE Status <> 0 AND Status <> 2);

(при условии, что Статус никогда не может быть НЕДЕЙСТВИТЕЛЕН), и оттуда только соединение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...