UPDATE COM SELECT COM ORDER BY

28/08/2023

0

Bom dia pessoal.
Não estou conseguindo fazer funcionar um UPDATE com um SELECT que contém um ORDER BY. Ressalto o ORDER BY porque o DBeaver mostra que é ali o problema, mas talvez nem seja. Segue o script pra ver se vocês conseguem me ajudar.

UPDATE ESCNREEQFINMEDICAO M SET
M.CDTABELA = (SELECT T.CDTABELA, T.RW
FROM (SELECT CDTABELA, ROWNUM RW FROM ESCNTABELA WHERE CDTABELA < 200 AND CDNATUREZA = 1 AND ROWNUM <= 13 ORDER by 1 DESC) T
INNER JOIN ESCNREEQFINMEDICAO RFM ON T.RW = RFM.NUMEDICAO
WHERE RFM.NUTITULO = 100839 ORDER BY T.CDTABELA ASC
) MM WHERE M.NUMEDICAO = MM.RW

A ideia é a seguinte. O primeiro SELECT CDTABELA, ROWNUM RW FROM ESCNTABELA ... traz um conjunto de dados que está ordenado de modo a trazer os maiores valores daquela tabela. Se eu não fizer aquele ORDER BY DESC, ele traz valores menores, do início da tabela.
CDTABELA RW
151 1
150 2
134 3
133 4
128 5
127 6
117 7
116 8
110 9
109 10
103 11
100 12
94 13

Com segundo SELECT SELECT T.CDTABELA, T.RW FROM... eu REordeno a pequena tabelinha de modo a fazer com o CDTABELA fique do menor pro maior.
94 13
100 12
103 11
109 10
110 9
116 8
117 7
127 6
128 5
133 4
134 3
150 2
151 1

Para daí então o M.CDTABELA ser atualizado. Na verdade enquanto eu escrevia essa questão aqui eu já vi um erro na minha lógica. Mas mesmo assim gostaria de ouvir seus comentários, por favor.

Obrigado desde já.
Carlo
Carlo Scopel

Carlo Scopel

Responder

Posts

28/08/2023

Jair N.

Boa Tarde veja abaixo, pois eu não tenho a base de dados comparativa...

UPDATE ESCNREEQFINMEDICAO M
SET CDTABELA = MM.CDTABELA
FROM (SELECT T.CDTABELA, T.RW
FROM (SELECT ES.CDTABELA
, RW = ROW_NUMBER()
OVER (ORDER BY ES.CDTABELA DESC)
FROM ESCNTABELA ES
WHERE (ES.CDTABELA < 200 )
AND (ES.CDNATUREZA = 1 )
AND (ES.RW <= 13 )
) T
INNER JOIN ESCNREEQFINMEDICAO RFM
ON (T.RW = RFM.NUMEDICAO)
WHERE (RFM.NUTITULO = 100839)
) MM
WHERE (M.NUMEDICAO = MM.RW)
Responder

28/08/2023

Arthur Heinrich

O que você está tentando fazer não faz sentido. A coluna ROWNUM não indica o número da linha após o order by, mas sim, a ordem em que a linha foi localizada. Portanto, fazer uma referência ao registro com base deste valor não tem significado algum para o negócio.

Além disso, para um update, não importa a ordem em que os registros são atualizados. Todos os registros são atualizados de forma atômica.

Vamos supor que a tabela ESCNREEQFINMEDICAO contém uma lista de 13 valores de CDTABELA, numerados sequencialmente de 1 a 13, sendo o 1 o maior CDTABELA e o 13, o menor.

A tabela ESCNTABELA recebe, de tempos em tempos, novos códigos de CDTABELA e você precisa identificar os últimos 13 CDTABELA contidos nesta tabela para atualizar a sua lista na outra tabela.

Para identificar os 13 CDTABELA maiores, você pode fazer o seguinte:

select CDTABELA, rownum rw
from
  ( select distinct CDTABELA
    from ESCNTABELA
    order by 1 desc )
where
  rownum <= 13


Com isto, você terá a sua lista. Agora, precisa atualizar a tabela ESCNREEQFINMEDICAO, para cada linha identificada por NUMEDICAO, identificando uma das linhas retornadas pela subquery (RW).

merge into ESCNREEQFINMEDICAO m
using ( select CDTABELA, rownum rw
        from
          ( select distinct CDTABELA
            from ESCNTABELA
            order by 1 desc )
        where
          rownum <= 13 ) mm
on ( m.NUMEDICAO = mm.RW )
when matched then
  update set
    m.CDTABELA = mm.CDTABELA;

Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar