Я обновляю столбец PREVIOUS_DAY_CLOSE
, содержащий значения DAY_CLOSE-1
.
Я использую функцию LAG()
для получения значений PREVIOUS_DAY_CLOSE
. Все работает нормально.
Но обновление столбца с помощью операторов UPDATE
и SELECT
, которые показывают ошибки.
Я попробовал запросы, показанные ниже, и получил следующие ошибки:
WITH t1 AS
(
SELECT
datetime,
LAG(CLOSE) OVER (ORDER BY datetime) AS PREVIOUS_CLOSE
FROM
stocks
WHERE
SYMBOL = 'NASDAQ:IXIC'
)
UPDATE STOCKS
SET PREVIOUS_CLOSE = t1.PREVIOUS_CLOSE
FROM t1
WHERE t1.datetime =STOCKS.datetime;
Я получаю эту ошибку:
ORA-00928: отсутствует ключевое слово SELECT
UPDATE STOCKS
SET PREVIOUS_CLOSE = (SELECT LAG(CLOSE) OVER (ORDER BY datetime) AS PREVIOUS_CLOSE
FROM STOCKS
WHERE SYMBOL = 'NASDAQ:IXIC');
Я получаю эту ошибку:
Ошибка SQL: ORA-01427: однострочный подзапрос возвращает более одной строки
Вы не можете использовать CTE непосредственно для обновления, но можете как часть выбора внутри обновления. В любом случае вам нужно сопоставить обновление, чего вы не совсем делаете, поскольку основываете это только на datetime
.
Как упоминалось в предыдущем вопросе, вам может потребоваться только предыдущее значение для отображения, которое вы можете получить с помощью простого запроса lag()
:
select symbol, datetime, open, close,
lag(close) over (partition by symbol order by datetime) as previous_close
from stocks
Но поскольку вы хотите обновить таблицу напрямую, вы можете использовать это как подзапрос либо в обновлении с запросом к встроенному представлению:
update stocks s
set previous_close = (
select previous_close
from (
select symbol, datetime,
lag(close) over (partition by symbol order by datetime) as previous_close
from stocks
) t
where t.symbol = s.symbol and t.datetime = s.datetime
)
или то же самое, но с CTE вместо встроенного представления:
update stocks s
set previous_close = (
with t (symbol, datetime, previous_close) as (
select symbol, datetime,
lag(close) over (partition by symbol order by datetime)
from stocks
)
select previous_close
from t
where t.symbol = s.symbol and t.datetime = s.datetime
)
Или вы можете использовать merge
вместо update
:
merge into stocks s
using (
select symbol, datetime,
lag(close) over (partition by symbol order by datetime) as previous_close
from stocks
) t
on (t.symbol = s.symbol and t.datetime = s.datetime)
when matched then update set s.previous_close = t.previous_close;
Все три имеют одинаковый результат;
select * from stocks order by symbol, datetime desc;
Я столкнулся с проблемой, когда присутствуют два символа, например: NASDAQ:META. Столбец PREVIOUS_CLOSE для NASDAQ:IXIC также обновляется случайным образом со значениями столбца NASDAQ:META CLOSE. Можете ли вы помочь мне, пожалуйста, помогите мне обновить значения PREVIOUS_CLOSE отдельно для каждого символа.
Я включил partition by symbol
и присоединился, используя этот столбец, чтобы избежать этого. Если это по-прежнему не работает, вам нужно будет задать новый вопрос с вашим текущим кодом, данными и результатами.
Я пробовал разделить по символу, но проблема все равно возникла. Меня заблокировали, чтобы я мог задавать новые вопросы.
Понятно. Я также включил раздел DATETIME с символом. Вот почему это вызывает проблемы. Я удалил DATETIME и все работает нормально.
ваша основная проблема заключается в том, что ваш подзапрос (тот, который вы ВЫБИРАЕТЕ из АКЦИЙ) возвращает более одной строки, исправление этого поможет вам получить ожидаемые результаты.
PS: Не забудьте предложениеwhere во втором запросе, хе-хе
см. stackoverflow.com/questions/7030699/…