2013-08-06 3 views
3

У меня есть запрос, который выглядит следующим образом:Неожиданное поведение в подзапрос

SELECT 'FY2000' AS FY, COUNT(DISTINCT SGBSTDN_PIDM) AS CHEM_MAJORS 
FROM SATURN.SGBSTDN, SATURN.SFRSTCR 
WHERE SGBSTDN_PIDM = SFRSTCR_PIDM 
    AND SGBSTDN_TERM_CODE_EFF = (SELECT MAX(SGBSTDN_TERM_CODE_EFF) 
           FROM SATURN.SGBSTDN 
           WHERE SGBSTDN_TERM_CODE_EFF <= '200002' 
           AND SGBSTDN_PIDM = SFRSTCR_PIDM) 
    AND SGBSTDN_MAJR_CODE_1 = 'CHEM' 
    AND SFRSTCR_TERM_CODE BETWEEN '199905' AND '200002' 
    AND (SFRSTCR_RSTS_CODE LIKE 'R%' OR SFRSTCR_RSTS_CODE LIKE 'W%') 
    AND SFRSTCR_CREDIT_HR >= 1 

Он возвращает счетчик 48, который я считаю, это правильно. Однако я не понимаю, почему подзапрос не нужен SATURN.SFRSTCR в предложении FROM для ссылки SFRSTCR_PIDM. Я думал, что подзапросы были самодостаточными и не могли увидеть остальную часть запроса?

Но, если я добавлю SATURN.SFRSTCR в подзапрос, счет будет изменен на 22. Если я возьму AND SGBSTDN_PIDM = SFRSTCR_PIDM из подзапроса, число также изменится на 22. Может ли кто-нибудь объяснить это мне?

ответ

6

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

При использовании коррелированных подзапросов всегда использует псевдонимы таблицы для всех ссылок на таблицы. Это хорошая идея в целом, но ее следует внимательно следить за коррелированными подзапросами.

AND SGBSTDN_TERM_CODE_EFF = (SELECT MAX(SGBSTDN.SGBSTDN_TERM_CODE_EFF) 
          FROM SATURN.SGBSTDN 
          WHERE SGBSTDN.SGBSTDN_TERM_CODE_EFF <= '200002' 
           AND SGBSTDN.SGBSTDN_PIDM = SFRSTCR.SFRSTCR_PIDM 
          ) 

Для каждого значения SFRSTCR.SFRSTCR_PIDM (и других условий), подзапрос получает максимальную дату.

В большинстве версий SQL коррелированные подзапросы разрешены в статьях from, where и having. (Они также могут быть разрешены в order by.)

2

Correlated subqueries (т. Е. Подзапросы внутри предложения WHERE), могут ссылаться на столбцы из внешнего запроса. Они отличаются от встроенными видами (то есть подзапросами внутри предложения FROM), которые не может видеть столбцы, определенные в родительском запросе.

Вы делаете это правильно: в подзапросе сначала будет искать столбец SFRSTCR_PIDM в его объеме (SATURN.SGBSTDN), затем идите и найдите его во внешнем запросе.

0

Подзапросы, которые вы указали, будут обрабатывать текущую запись на внешнем уровне, который будет обрабатываться, и сделать ДОСТУПНЫ к второму запросу, поэтому вам явно не нужно включать его в свой подзапрос. Если столбец уникально идентифицирован, вам не нужна ссылка alias.column и может просто уйти с ссылкой на columnName.

Однако подзапросы, как правило, очень плохие по производительности, поскольку подпроцесс выполняется для обрабатываемой КАЖДОЙ записи. Обычно используются соединения, но каждый запрос имеет свои собственные потребности, и вы получаете MAX() на уровне подзапроса.

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