#sql #oracle #nested
#sql #Oracle #вложенный
Вопрос:
Надеюсь, название имеет какой-то смысл — в принципе, я хотел бы выполнить вложенный выбор на основе значения в исходном выборе, вот так:
SELECT MAX(iteration) AS maxiteration,
(SELECT column
FROM table
WHERE id = 223652
AND iteration = maxiteration)
FROM table
WHERE id = 223652;
Я получаю ошибку недопустимого идентификатора ORA-00904.
Был бы очень признателен за любой совет о том, как вернуть это значение, спасибо!
Комментарии:
1. Можете ли вы опубликовать полное сообщение об ошибке?
2. Так много замечательных ответов, спасибо вам, ребята!
Ответ №1:
Похоже, это должно быть переписано с помощью предложения where:
select iteration,
col
from tbl
where id = 223652
and iteration = (select max(iteration) from tbl where id = 223652);
Комментарии:
1. 1 : Моя предпочтительная версия, но я бы изменил 2-й экземпляр
223652
, чтобы ссылаться на идентификатор из внешнего запроса. (Но также потребуется, чтобы одному экземпляруtbl
был присвоен псевдоним.)
Ответ №2:
Вы можете полностью обойти проблему, поместив подвыборку в INNER JOIN
свою собственную.
SELECT t.iteration
, t.column
FROM table t
INNER JOIN (
SELECT id, MAX(iteration) AS iteration
FROM table
WHERE id = 223652
) tm ON tm.id = t.id AND tm.iteration = t.iteration
Комментарии:
1. Потому что немногие СУБД допускают использование псевдонима агрегатной функции в качестве ссылки в коррелированном подзапросе. Если бы это было разрешено, был бы каскад зависимостей (коррелированный результат подзапроса мог быть использован в другом коррелированном подзапросе). И это может даже привести к циклическим ссылкам и другим сложностям. Итак, в общем, это просто не разрешается. (Ответ Дэниела Хилгарта — это обходной путь, наиболее точно соответствующий ответу OP.)
Ответ №3:
Поскольку вы используете Oracle, я бы предложил использовать для этого аналитические функции:
SELECT * FROM (
SELECT col,
iteration,
row_number() over (partition by id order by iteration desc) rn
FROM tab
WHERE id = 223652
) WHERE rn = 1
Ответ №4:
сделайте это следующим образом:
with maxiteration as
(
SELECT MAX(iteration) AS maxiteration
FROM table
WHERE id = 223652
)
select
column,
iteration
from
table
where
id = 223652
AND iteration = maxiteration
;
Ответ №5:
Не уверен на 100% в синтаксисе Oracle, но разве это не что-то вроде:
select iteration, column from table where id = 223652 order by iteration desc limit 1
Ответ №6:
Я бы подошел к этой проблеме немного по-другому. По сути, вы ищете строку, у которой нет других итераций, превышающих ее. Я могу придумать как минимум 3 способа сделать это:
SELECT
T1.iteration AS maxiteration,
T1.column
FROM
Table T1
WHERE
T1.id = 223652 AND
NOT EXISTS
(
SELECT *
FROM Table T2
WHERE
T2.id = 223652 AND
T2.iteration > T1.iteration
)
Или…
SELECT
T1.iteration AS maxiteration,
T1.column
FROM
Table T1
LEFT OUTER JOIN Table T2 ON
T2.id = T1.id AND
T2.iteration > T1.iteration
WHERE
T1.id = 223652 AND
T2.id IS NULL
Или…
SELECT
T1.iteration AS maxiteration,
T1.column
FROM
Table T1
INNER JOIN (SELECT id, MAX(iteration) AS maxiteration FROM Table T2 GROUP BY id) SQ ON
SQ.id = T1.id AND
SQ.maxiteration = T1.iteration
WHERE
T1.id = 223652
РЕДАКТИРОВАТЬ: я не увидел ошибку ORA при первом чтении вопроса, и она не была помечена как специфичная для Oracle. Я думаю, что могут быть некоторые различия в синтаксисе и использовании псевдонимов в Oracle, поэтому вам может потребоваться настроить некоторые из приведенных выше запросов.
Ошибка Oracle сообщает вам, что он не знает, что такое maxiteration, поскольку псевдоним столбца пока недоступен внутри подзапроса. Вам нужно ссылаться на него с помощью псевдонима таблицы и имени столбца вместо псевдонима столбца, который я полагаю.
Ответ №7:
Вы делаете что-то вроде
select maxiteration,column from table a join (select max(iteration) as maxiteration from table where id=1) b using (id) where b.maxiteration=a.iteration;
Это, конечно, может возвращать несколько строк для одного maxiteration, если в вашей таблице нет ограничения на это.