Коррелированный подзапрос Oracle в списке FROM - PullRequest
1 голос
/ 04 марта 2009

Я только что попытался сделать коррелированный подзапрос в предложении FROM оператора SELECT в Oracle, но мне выдали ошибку, указывающую, что я не мог сделать корреляцию (что-то, что Obs.pID не был признан).

Должно ли это работать?

FROM ml.Person Person 
    JOIN ml.Obs ON Person.pID = Obs.pId
        JOIN (SELECT ObsMax2.pId, ObsMax2.hdId
                , MAX(ObsMax2.obsDate) as maxDate
                FROM ml.Obs ObsMax2
                WHERE ObsMax2.pId = Obs.pId
                    AND ObsMax2.obsDate < {?EndDate}
                GROUP BY ObsMax2.pId, ObsMax2.hdId) ObsMax 
            ON Obs.pId = ObsMax.pId
                AND Obs.hdId = ObsMax.hdId
                AND Obs.obsDate = ObsMax.maxDate

Мой обходной путь может заключаться в том, чтобы сделать его некоррелированным подзапросом и добавить критерии в подзапрос, которые не позволяют ему работать полностью amuck, amuck, amu - oof Извините.

Я бы предпочел выяснить, как правильно соотнести его, хотя, если возможно - представление, которое работает как этот подзапрос, строится вечно.

Ответы [ 3 ]

4 голосов
/ 05 марта 2009

Вы можете достичь цели этой части запроса, используя аналитическую функцию, чтобы определить максимальное значение obsDate для каждого pid и hdid.

Это было бы что-то вроде:

select ...
from   (
       SELECT pId,
              hdId,
              obsDate
              MAX(obsDate) over (partition by pId, hdId) maxDate
       FROM   ml.Obs
       WHERE  obsDate < {?EndDate}
       )
where  obsDate = maxDate
/
3 голосов
/ 04 марта 2009

Подзапросы в предложении FROM не могут ссылаться на другие таблицы из того же предложения FROM. Удаление предложения ObsMax2.pId = Obs.pId должно решить проблему, и, насколько я могу судить, даст вам точно такой же результат, так как то же предложение находится в условии соединения. Однако, как вы упомянули, у вас могут возникнуть проблемы с производительностью при наличии GROUP BY в подзапросе.

Из того, что я могу сказать, вы пытаетесь получить отдельные записи pID / hdId из ml.Obs с наибольшим obsDate, который меньше, чем {EndDate}. В этом случае, как насчет перемещения подзапроса в предложение WHERE, где вы можете соотнести его? E.g.:

select ...
from
  ml.Person Person
  join ml.Obs on Person.PID = Obs.pId
where Obs.obsDate = (
    select max(obsDate)
    from ml.Obs Obs2
    where Obs2.pId = Obs.pId
      and obs2.hdId = Obs.hdId
      and Obs2.obsDate < {EndDate})
0 голосов
/ 04 марта 2009

Вы поставили перед многими таблицами префикс "ml". но не везде (первое присоединение, например). Предполагая, что вам нужно это (для пользователя / разрешения / что угодно):

ПРИСОЕДИНИТЬСЯ к мл. Obs ON Person.pID = ** ml. ** Obs.pId

или

ПРИСОЕДИНИТЬСЯ к ml.Obs Obs ON Person.pID = Obs.pId

Есть и другие места, где это было бы необходимо.

Если это не так, удалите их из запроса, потому что они не имеют значения и отвлекают.

...