diogoarsousa Posted March 12, 2015 at 10:27 AM Report Share #579197 Posted March 12, 2015 at 10:27 AM ' Bom dia ' Tenho uma tabela chamada Caudais com com os seguintes campos = ID, Date e Caudal ' A tabela está ordenada por ID e Date ' Sei que existem registos duplicados, triplicados, etc. com o mesmo ID e Date ' Quero que o programa corra todos os registos da tabelam que compare cada um com o seguinte e apague o que tiver menor caudal. ' No entanto este programa nao está a funcionar convenientemente. Alguém me pode ajudar a corrigi-lo e a simplificá-lo? Obrigado Dim Previous_ID As Integer Dim Previous_Date As Integer Dim Previous_Caudal as Integer Dim Next_ID As Integer Dim Next_Date As Integer Dim Next_Caudal As Integer Dim Sqlstring as string 'Apago os registos importados duplicados na Base de Dados Sqlstring = "SELECT * FROM Caudais WHERE Caudais.Date >= " & "20150101" New ADODB.Recordset() rst.Open(Sqlstring, "DSN=Diogo", ADODB.CursorTypeEnum.adOpenKeyset, ADODB.LockTypeEnum.adLockOptimistic, ADODB.CommandTypeEnum.adCmdText) rst.MoveFirst() [indent=1] Do Until (rst.EOF) Previous_ID = rst.Fields("ID").Value Previous_Date = rst.Fields("Date").Value Previous_Caudal = rst.Fields("Caudal").Value rst.MoveNext() If Not rst.EOF Then Next_ID = rst.Fields("ID").Value Next_Data = rst.Fields("Date").Value Next_Caudal = rst.Fields("Caudal").Value If Previous_ID = Next_ID And Previous_Date = Next_Date Then If Previous_Caudal <= Next_Caudal Then rst.Delete(ADODB.AffectEnum.adAffectCurrent) rst.Requery() Else rst.MovePrevious() rst.Delete(ADODB.AffectEnum.adAffectCurrent) rst.Requery() End If End If End If[/indent] Loop rst.Close() rst = Nothing Link to comment Share on other sites More sharing options...
passarito Posted March 12, 2015 at 06:41 PM Report Share #579242 Posted March 12, 2015 at 06:41 PM Onde está a dar o erro? Que erro é que está a dar? Para já, com esse código o programa só está a trabalhar nas datas superiores ou iguais a 20150101 Link to comment Share on other sites More sharing options...
diogoarsousa Posted March 13, 2015 at 09:42 AM Author Report Share #579304 Posted March 13, 2015 at 09:42 AM Olá CRLF, Eu só pretendo verificar as datas superiores ou iguais a 20150101. E depois de o correr há muitos registos duplicados que não são apagados Para simplificar a apresentação do problema eu retirei o campo Hora que agora acrescento. A questão é que depois de criar o recorset, quando faço - rst.MoveFirst() - o programa salta logo para o registo em que a hora é 330 Agora o programa completo Dim Previous_ID As Integer Dim Previous_Hora As Integer Dim Previous_Data As Integer Dim Previous_Caudal as Integer Dim Next_ID As Integer Dim Next_Hora As Integer Dim Next_Data As Integer Dim Next_Caudal As Integer Dim Sqlstring as string 'Apago os registos importados duplicados na Base de Dados Sqlstring = "SELECT * FROM Caudais WHERE ZMC_Caudais.Data >= " & "20150101" New ADODB.Recordset() rst.Open(Sqlstring, "DSN=Diogo", ADODB.CursorTypeEnum.adOpenKeyset, ADODB.LockTypeEnum.adLockOptimistic, ADODB.CommandTypeEnum.adCmdText) rst.MoveFirst() Do Until (rst.EOF) Previous_ID = rst.Fields("ID_ZMC").Value Previous_Hora = rst.Fields("Hora").Value Previous_Data = rst.Fields("Data").Value Previous_Caudal = rst.Fields("Caudal").Value rst.MoveNext() If Not rst.EOF Then Next_ID = rst.Fields("ID_ZMC").Value Next_Hora = rst.Fields("Hora").Value Next_Data = rst.Fields("Data").Value Next_Caudal = rst.Fields("Caudal").Value If Previous_ID = Next_ID And Previous_Hora = Next_Hora And Previous_Data = Next_Data Then If Previous_Caudal <= Next_Caudal Then rst.Delete(ADODB.AffectEnum.adAffectCurrent) rst.Requery() Else rst.MovePrevious() rst.Delete(ADODB.AffectEnum.adAffectCurrent) rst.Requery() End If End If End If Loop rst.Close() rst = Nothing ZMC_Caudais ID_ZMC Data Hora Caudal 101 20150101 15 0 101 20150101 30 1 101 20150101 45 5 101 20150101 100 5 101 20150101 115 2 101 20150101 130 1 101 20150101 145 5 101 20150101 200 9 101 20150101 215 10 101 20150101 230 2 101 20150101 245 14 101 20150101 300 6 101 20150101 315 0 101 20150101 330 0 101 20150101 345 7 101 20150101 400 0 101 20150101 415 0 101 20150101 430 0 101 20150101 445 0 101 20150101 500 0 101 20150101 515 1 101 20150101 530 2 101 20150101 545 0 101 20150101 600 6 101 20150101 615 0 Link to comment Share on other sites More sharing options...
diogoarsousa Posted March 13, 2015 at 09:52 AM Author Report Share #579306 Posted March 13, 2015 at 09:52 AM Não sei porque é apareceram tanto «color» no código No fim estão alguns registos da tabela ZMC_Caudais com os quatro campos É pena que não seja possível carregar uma imagem a partir do disco. Obrigado Link to comment Share on other sites More sharing options...
passarito Posted March 13, 2015 at 11:45 AM Report Share #579322 Posted March 13, 2015 at 11:45 AM (edited) Boas, Na declaração SQL ordena a tabela por ID_ZMC, Data e Hora P.S. O meu user não é CRLF, assim como o teu também não é void Edited March 13, 2015 at 11:47 AM by passarito Link to comment Share on other sites More sharing options...
diogoarsousa Posted March 13, 2015 at 02:03 PM Author Report Share #579331 Posted March 13, 2015 at 02:03 PM (edited) Muito obrigado passarito 👍 A ordenação da tabela por ID_ZMC, Data e Hora resolveu o problema de o programa saltar logo para o registo em que a hora é 330. Agora vai para o 1º registo. Mas causa-me estranheza porque ao olhar para a tabela, ela parecia (aparentemente) ordenada. Quanto à outra questão, a de comparar dois registos consecutivos e apagar o de caudal menor, qual é a forma mais correcta de fazer?: Do Until (rst.EOF) Previous_ID = rst.Fields("ID_ZMC").Value Previous_Hora = rst.Fields("Hora").Value Previous_Data = rst.Fields("Data").Value Previous_Caudal = rst.Fields("Caudal").Value rst.MoveNext() If Not rst.EOF Then Next_ID = rst.Fields("ID_ZMC").Value Next_Hora = rst.Fields("Hora").Value Next_Data = rst.Fields("Data").Value Next_Caudal = rst.Fields("Caudal").Value If Previous_ID = Next_ID And Previous_Hora = Next_Hora And Previous_Data = Next_Data Then If Previous_Caudal <= Next_Caudal Then rst.Delete(ADODB.AffectEnum.adAffectCurrent) rst.Requery() Else rst.MovePrevious() rst.Delete(ADODB.AffectEnum.adAffectCurrent) rst.Requery() End If End If End If Loop rst.Close() rst = Nothing Edited March 13, 2015 at 02:14 PM by diogoarsousa Link to comment Share on other sites More sharing options...
passarito Posted March 13, 2015 at 02:53 PM Report Share #579333 Posted March 13, 2015 at 02:53 PM Cada programador tem as suas próprias técnicas/hábitos de rotinas de programação. Dito isto, é claro que não faria a rotina desta forma, no entanto parece-me que o problema aqui coloca-se quando o programa apaga um registo, independentemente de ser o anterior ou posterior, pois quando ele vai atribuir os valores do registo anterior não sei o que ele fará. Para solucionar este problema colocaria o bloco onde é atribuído os valores do registo anterior em dois sitios: - Imediatamente antes do inicio do ciclo "Do until" para garantir que entra no ciclo com esses valores - No "else" do "if" de comparação dos valores anteriores e posteriores, pois quando apagas é porque os registos são iguais, se são iguais não vale a pena re-atribuir os valores do anterior Por fim, quando se apaga o registo anterior, neste caso tem de se atribuir ao Previous_Caudal o valor do Next_Caudal Só em nota de rodapé, há que ter em atenção se quando se lê um registo o ponteiro continua a apontar para esse registo ou para o seguinte, pois há programas que trabalham dessa forma. Se for o caso, para apagares o registo actual tens de andar uma vez para trás, se for o registo anterior terás de andar duas vezes para trás Link to comment Share on other sites More sharing options...
diogoarsousa Posted March 13, 2015 at 03:14 PM Author Report Share #579336 Posted March 13, 2015 at 03:14 PM (edited) Compreendo Passarito. E como é que tu farias esta rotina? Edited March 13, 2015 at 03:14 PM by diogoarsousa Link to comment Share on other sites More sharing options...
passarito Posted March 13, 2015 at 04:22 PM Report Share #579340 Posted March 13, 2015 at 04:22 PM Para este tipo de operação não costumo usar o "DO". Uso o "While" e isso muda a forma de sequenciar o fluxo de informação. Mas não vás refazer uma rotina toda por este motivo, além do mais não há uma forma melhor do que outra, antes aquela a que estamos mais habituados. É uma abordagem diferente mas de igual modo válida e correcta. Se essa já está quase a funcionar, implementa lá as alterações que te disse e diz qualquer coisa. Link to comment Share on other sites More sharing options...
diogoarsousa Posted March 16, 2015 at 10:39 AM Author Report Share #579517 Posted March 16, 2015 at 10:39 AM (edited) Obrigado pela ajuda, passarito. Abraço Edited March 16, 2015 at 10:39 AM by diogoarsousa Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now