Como condicionar o select em outra linha da tabela no Mysql?
17/02/2020
0
Basicamente eu tenho dados de indivíduos em anos seguidos (2003, 2004, 2005) todos em uma mesma tabela. Além desses dados, disponho de informações, por exemplo, da escolaridade (que pode mudar ano após ano, ou manter-se constante).
Porém alguns registros da minha base de dados são inconsistentes, por exemplo, selecionando os primeiros registros ordenados pelo cpf e pelo ano, temos (mudei o cpf por motivos de sigilo dos dados):
Ano CPF Escolaridade 2004 10000000kkk 3 2005 10000000kkk 5 2003 10000000zzz 7 2005 10000000zzz 6 2003 10000000ttt 7 2005 10000000ttt 4 2004 10000000ppp 6 2005 10000000ppp 9 2004 10000000sss 7 2005 10000000sss 9 2005 10000000sss 9 2003 10000002xxx 6 2005 10000002xxx 7
A escolaridade é codificada:
ANALFABETO 1 ATE 5.A INC 2 5.A CO FUND 3 6. A 9. FUND 4 FUND COMPL 5 MEDIO INCOMP 6 MEDIO COMPL 7 SUP. INCOMP 8 SUP. COMP 9 MESTRADO 10 DOUTORADO 11 IGNORADO -1
Minha dúvida é: como posso filtrar essas inconsistências? Alguém pode me ajudar?
Amanda Uceli
Posts
17/02/2020
Anderson Gonçalves
17/02/2020
Amanda Uceli
Eu tenho indivíduos que diminuem a escolaridade de um ano para o outro, ou que mudam de forma desproporcional (em um ano são registrados com ensino fundamental, e no seguinte com ensino superior completo, por exemplo).
17/02/2020
Amanda Uceli
Qual código? Da busca pela inconsistência?
Já fiz várias tentativas e nenhuma funcionou.
Tentativa 1:
select ano, escolaridade, cpf from id2003to2005 k1, id2003to2005 k2 where k1.cpf = k2.cpf and k1.chave_2 != k2.chave_2 and ((k1.ano - k2.ano=1) and ((k1.escolaridade - k2.escolaridade>1 or k1.escolaridade - k2.escolaridade<0)) or ( (k1.ano - k2.ano>1) and (k1.escolaridade - k2.escolaridade>2 or k1.escolaridade - k2.escolaridade<0)));
Tentativa 2:
select k1.ano, k1.escolaridade, k1.chave_2, k1.cpf, k2.ano, k2.escolaridade, k2.chave_2, k3.cpf from id2003to2005 k1 inner join id2003to2005 k3 on k1.cpf=k3.cpf inner join id2003to2005 k2 where ((k1.ano - k2.ano=1) and ((k1.escolaridade - k2.escolaridade>1 or k1.escolaridade - k2.escolaridade<0)) or ( (k1.ano - k2.ano>1) and (k1.escolaridade - k2.escolaridade>2 or k1.escolaridade - k2.escolaridade<0))) and k3.chave_2 != k1.chave_2;
Tentativa 3 (sugerida em outro fórum):
create temporary table tabela_temporaria select MAX(ano) as ano, cpf, 0 as valor_atual, 0 as valor_anterior from id2003to2005 group by cpf; update tabela_temporaria as T set valor_atual = (SELECT escolaridade from id2003to2005 as P WHERE P.ano = T.ano and P.cpf = T.cpf LIMIT 1) ; update tabela_temporaria as T set valor_anterior = (SELECT escolaridade from id2003to2005 as P WHERE P.ano < T.ano and P.cpf = T.cpf ORDER BY ano DESC limit 1); select * from tabela_temporaria WHERE valor_anterior > valor_atual or (abs(valor_atual - valor_anterior)> 2 and valor_anterior>6) ;
Os querys ficam rodando por muito tempo e não finalizam. É importante dizer que tenho uma quantidade enorme de linhas, mais 100 milhões. Eu sei que com esse volume de dados tudo fica mais lento, mas essas tentativas não funcionaram mesmo.
17/02/2020
Mauricio Espido
Eu traria todos esses dados num select. E então passaria essa informação para uma tabela virtual e mandaria para uma function, lá você pode comparar
os dados e separar os divergentes.
No Oracle costumo montar uma type table e alimentar as linhas com a informação separada dentro da function.
17/02/2020
Amanda Uceli
Eu traria todos esses dados num select. E então passaria essa informação para uma tabela virtual e mandaria para uma function, lá você pode comparar
os dados e separar os divergentes.
No Oracle costumo montar uma type table e alimentar as linhas com a informação separada dentro da function.
Então, eu preciso do próximo registro, mas o que eu quero é excluir da base de dados todos os indivíduos (todas as ocorrencias do cpf inconsistente) que apresentam incongruências nos registro de escolaridade. Eu preciso comparar a escolaridade do indivíduo entre os anos e retirar aqueles que apresentam a inconsistência.
18/02/2020
Emerson Nascimento
-- COM CERTEZA ESTÃO ERRADOS, PORQUE A ESCOLARIDADE DO ANO ATUAL -- É MAIOR QUE A ESCOLARIDADE DO ANO SEGUINTE SELECT DISTINCT T.CPF FROM ( SELECT CPF, ANO, ESCOLARIDADE, LEAD(ESCOLARIDADE,1,ESCOLARIDADE) OVER ( PARTITION BY CPF ORDER BY ANO, ESCOLARIDADE) PROX_ESCOLARIDADE FROM GRADUACAO ) T WHERE T.CPF IN (SELECT CPF FROM GRADUACAO GROUP BY CPF HAVING COUNT(*) > 1) AND T.ESCOLARIDADE > T.PROX_ESCOLARIDADE
agora precisa montar um script pra pegar os demais casos. aqueles
18/02/2020
Amanda Uceli
-- COM CERTEZA ESTÃO ERRADOS, PORQUE A ESCOLARIDADE DO ANO ATUAL -- É MAIOR QUE A ESCOLARIDADE DO ANO SEGUINTE SELECT DISTINCT T.CPF FROM ( SELECT CPF, ANO, ESCOLARIDADE, LEAD(ESCOLARIDADE,1,ESCOLARIDADE) OVER ( PARTITION BY CPF ORDER BY ANO, ESCOLARIDADE) PROX_ESCOLARIDADE FROM GRADUACAO ) T WHERE T.CPF IN (SELECT CPF FROM GRADUACAO GROUP BY CPF HAVING COUNT(*) > 1) AND T.ESCOLARIDADE > T.PROX_ESCOLARIDADE
agora precisa montar um script pra pegar os demais casos. aqueles
Emerson, sua proposta faz sentido, mas por alguma razão que eu desconheço, há um erro na sintaxe do comando. Já tentei descobrir onde o erro se encontra, mas não achei. Tentei criar uma tabela auxiliar apenas com a definição de T, mas segue apontando erro de sintaxe.
18/02/2020
Renato Neto
Entendido o problema e com as inconsistências tratadas eu partiria para a comparação, talvez utilizando um self-join ou com o auxilio de tabelas temporárias.
18/02/2020
Amanda Uceli
Entendido o problema e com as inconsistências tratadas eu partiria para a comparação, talvez utilizando um self-join ou com o auxilio de tabelas temporárias.
Renato os cpfs são numéricos. Eu mudei o final porque se trata de dados reais e para os quais deve-se manter o sigilo.
No caso, como eu disse em uma resposta acima, eu estou lidando com um volume muito grande de dados (mais de 100 milhões de linhas), e qualquer análise individual é totalmente inviável. Eu tenho algumas possibilidades de inconsistências, mas ainda que eu verifique todas as possibilidade relativas à escolaridade, eu não estou conseguindo comparar a escolaridade do mesmo cpf ao longo dos anos. E é exatamente isso que eu preciso.
18/02/2020
Emerson Nascimento
-- COM CERTEZA ESTÃO ERRADOS, PORQUE A ESCOLARIDADE DO ANO ATUAL -- É MAIOR QUE A ESCOLARIDADE DO ANO SEGUINTE SELECT DISTINCT T.CPF FROM ( SELECT CPF, ANO, ESCOLARIDADE, LEAD(ESCOLARIDADE,1,ESCOLARIDADE) OVER ( PARTITION BY CPF ORDER BY ANO, ESCOLARIDADE) PROX_ESCOLARIDADE FROM GRADUACAO ) T WHERE T.CPF IN (SELECT CPF FROM GRADUACAO GROUP BY CPF HAVING COUNT(*) > 1) AND T.ESCOLARIDADE > T.PROX_ESCOLARIDADE
agora precisa montar um script pra pegar os demais casos. aqueles
Emerson, sua proposta faz sentido, mas por alguma razão que eu desconheço, há um erro na sintaxe do comando. Já tentei descobrir onde o erro se encontra, mas não achei. Tentei criar uma tabela auxiliar apenas com a definição de T, mas segue apontando erro de sintaxe.
Publique o erro apresentado.
18/02/2020
Amanda Uceli
-- COM CERTEZA ESTÃO ERRADOS, PORQUE A ESCOLARIDADE DO ANO ATUAL -- É MAIOR QUE A ESCOLARIDADE DO ANO SEGUINTE SELECT DISTINCT T.CPF FROM ( SELECT CPF, ANO, ESCOLARIDADE, LEAD(ESCOLARIDADE,1,ESCOLARIDADE) OVER ( PARTITION BY CPF ORDER BY ANO, ESCOLARIDADE) PROX_ESCOLARIDADE FROM GRADUACAO ) T WHERE T.CPF IN (SELECT CPF FROM GRADUACAO GROUP BY CPF HAVING COUNT(*) > 1) AND T.ESCOLARIDADE > T.PROX_ESCOLARIDADE
agora precisa montar um script pra pegar os demais casos. aqueles
Emerson, sua proposta faz sentido, mas por alguma razão que eu desconheço, há um erro na sintaxe do comando. Já tentei descobrir onde o erro se encontra, mas não achei. Tentei criar uma tabela auxiliar apenas com a definição de T, mas segue apontando erro de sintaxe.
Publique o erro apresentado.
O programa acusa um erro de sintaxe no primeiro select do comando.
Clique aqui para fazer login e interagir na Comunidade :)