Acho que isso deve ser uma coisa bastante comum de se fazer, mas não consegui encontrar um exemplo. Envolve a mesclagem de dados que envolvem datas/horas (ou mais geralmente quaisquer valores sequenciais) sem incluir registros redundantes. Por redundante, quero dizer registros que podem ser implícitos em outros registros.
Por exemplo, se o preço ontem foi $ 1 e o preço hoje é $ 1, e não houve outras mudanças de preço entre ontem e hoje, então o preço hoje pode ser inferido a partir do preço ontem sem armazenar um preço para ambos os dias.
Aqui está o cenário que estou tentando resolver. Temos uma tabela de preços históricos dos itens. Novos preços são importados periodicamente para a tabela. O arquivo de importação pode conter datas de qualquer época, não sabemos se elas estão sempre "depois" dos dados na tabela de histórico.
Para evitar o inchaço dos dados, só quero inserir registros se eles fornecerem novas informações. Portanto, se um novo registro puder ser inferido de um registro antigo, não desejo inserir o novo registro e, se um registro antigo puder ser inferido de um novo registro, desejo remover o registro antigo e inserir o novo registro.
Alguns exemplos concretos podem ajudar, aqui estão os dois cenários de problemas:
Um registro de entrada pode ser inferido de um registro existente, portanto, o registro de entrada é redundante. Por exemplo
recorde antigo: 23/04/2013 1,00
novo registro: 2013-04-24 1.00 <-- isso está implícito no registro existente, não o insira
Um registro existente pode ser inferido de um novo registro, portanto, o registro existente é redundante. Por exemplo
novo recorde: 2013-04-23 1,00
registro antigo: 2013-04-24 1.00 <-- isso está implícito no novo registro, exclua-o
Isso apenas mostra um exemplo de quando um valor não é redundante. Por exemplo
recorde antigo: 23/04/2013 1,00
recorde antigo: 2013-04-24 1.20
novo recorde: 2013-04-25 1,00 <-- não redundante, o preço mudou desde o último 1,00
Há um exemplo mais detalhado aqui http://sqlfiddle.com/#!3/2ef87/2
Atualmente, estou inclinado para uma abordagem de várias etapas de:
- Excluir da entrada onde houver um registro existente que tenha o mesmo preço com uma data anterior (cenário 1 acima).
- Excluir de existente onde houver um registro de entrada que tenha o mesmo preço com uma data anterior (cenário 2 acima).
- Insira os registros de entrada restantes.
Deve haver uma maneira melhor, talvez usando MERGE, mas está me dando trabalho tentando descobrir como fazê-lo.
Como faço para "mesclar" com eficiência os registros existentes e recebidos? Obrigado
A questão dos registros que chegam atrasados torna a remoção de duplicatas mais complexa, mas não é impossível. Usar uma exibição (conforme proposto em sua outra pergunta ) para remover duplicatas dinamicamente é viável, mas as consultas nessa exibição podem produzir planos de consulta complexos e/ou ineficientes.
Um design alternativo é manter os registros duplicados em uma tabela separada, caso sejam necessários para processar adequadamente um futuro registro atrasado. Isso adiciona um pouco de complexidade ao processo de importação de dados, mas cada etapa não é muito difícil e o resultado é uma bela tabela de histórico limpa e livre de duplicatas:
Tabelas
Dados iniciais
O primeiro passo é remover quaisquer redundâncias nos dados de entrada, armazenando os dados removidos na nova tabela de retenção:
Classificando linhas de entrada
A próxima etapa é decidir se cada linha na tabela de entrada é redundante (gravar a tabela Histórico) ou não. A consulta a seguir define a
Action
coluna dos dados do conjunto de entrada apropriadamente:Armazenar linhas redundantes
Agora armazenamos as linhas identificadas como redundantes na tabela de retenção:
Novas linhas do histórico
As linhas não redundantes são adicionadas à tabela Histórico:
Restaurando registros redundantes
Adicionar novos registros pode resultar em linhas redundantes que precisam ser restabelecidas. A consulta a seguir identifica as linhas redundantes qualificadas e as move para a tabela Histórico:
Resultados
tabela de histórico
Tabela de Duplicatas do Histórico
Processando novos dados
As etapas anteriores são bastante gerais. Podemos processar um novo lote de linhas usando exatamente o mesmo código. O próximo script carrega a tabela de entrada com duas linhas de amostra, uma das quais é duplicada e a outra é um exemplo da necessidade de restabelecer uma linha redundante anteriormente:
A execução do restante do script geral produz este estado final:
História:
Histórico Duplicado:
(isso é mais uma consulta ou um "tem certeza que realmente quer fazer isso?" do que uma resposta, desculpe, mas é muito longo para um comentário!)
Se os dados anteriores puderem chegar mais tarde, você realmente deseja excluir alguma coisa? Um novo ponto de dados pode aparecer, o que significa que você precisava manter algo que removeu, por exemplo:
então
entra e você desduplica
para
mas então
chega, e você gostaria
não
mas você excluiu o valor para o 4º.
Como os dados do passado podem chegar agora, você pode precisar manter tudo e usar uma exibição para filtrar duplicatas quando quiser apenas considerar as alterações de valor em vez de cada leitura.
Se eu entendi corretamente:
Isso pode ser feito usando uma cláusula MERGE como esta:
Verifique neste violino para ver se este é o resultado que você deseja.