o SELECT trás corretamente o último preço reajustado.
Mensagem( "Anulando reajuste" )
WITH OBJECT cnSQL
:cSQL := "SELECT IDPREHIS, PHPRODUTO, PHCADASTRO, PHFORPAG, PHVALOR FROM JPPREHIS" + ;
" INNER JOIN" + ;
" ( SELECT MAX( IDPREHIS ) AS ULTIMOLANC FROM JPPREHIS GROUP BY PHPRODUTO, PHCADASTRO, PHFORPAG ) AS ULTIMO" + ;
" ON JPPREHIS.IDPREHIS = ULTIMO.ULTIMOLANC" + ;
" ORDER BY PHPRODUTO, PHCADASTRO, PHFORPAG"
:Execute()
DO WHILE ! :Eof()
SELECT jppreco
SEEK StrZero( :Number( "PHPRODUTO" ), 6 ) + StrZero( :Number( "PHCADASTRO", 6 ) ) + StrZero( :Number( "PHFORPAG" ), 6 )
IF ! Eof()
:QueryCreate()
:QueryAdd( "PCVALOR", :Number( "PHVALOR" ) )
jppreco->( :DBFQueryExecuteUpdate( "JPPRECO" ) )
:QueryExecuteUpdate( "JPPRECO", "IDPRECO = " + NumberSQL( jppreco->idPreco ) )
ENDIF
:MoveNext()
ENDDO
:CloseRecordset()
ENDWITH
Agora é SQL.
Imaginei: se isso trás certo, basta usar o resultado disso.
Mensagem( "Anulando reajuste" )
WITH OBJECT cnSQL
:cSQL := "UPDATE JPPRECO" + ;
" INNER JOIN ( " + ;
" SELECT IDPREHIS, PHPRODUTO, PHCADASTRO, PHFORPAG, PHVALOR FROM JPPREHIS" + ;
" INNER JOIN" + ;
" ( SELECT MAX( IDPREHIS ) AS ULTIMOLANC FROM JPPREHIS GROUP BY PHPRODUTO, PHCADASTRO, PHFORPAG ) AS ULTIMO" + ;
" ON JPPREHIS.IDPREHIS = ULTIMO.ULTIMOLANC ) AS A" + ;
;
" ON A.PHPRODUTO = JPPRECO.PCPRODUTO AND A.PHCADASTRO = JPPRECO.PCCADASTRO" + ;
" AND A.PHFORPAG = JPPRECO.PCFORPAG" + ;
" SET JPPRECO.PCVALOR = A.PHVALOR" + ;
" WHERE A.PHPRODUTO = JPPRECO.PCPRODUTO AND A.PHCADASTRO = JPPRECO.PCCADASTRO AND A.PHFORPAG = JPPRECO.PCFORPAG"
:ExecuteCmd()
ENDWITH
A dúvida é se precisa o WHERE quando usa INNER JOIN.
A intenção é não mexer em preços que não existem no histórico.
A chave do preço é produto + cadastro + forma de pagamento
No final o INNER JOIN e o WHERE estão fazendo a mesma coisa exceto que o WHERE impede NULL, e o INNER JOIN "talvez" também.