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
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
Curtir tópico
+ 0
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)
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:
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).
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
Clique aqui para fazer login e interagir na Comunidade :)