Tabela de remoção de dados do servidor SQL
as colunas são: Primeiro, Último, dob, endereço, cidade,estado, zip, telefone e estão em uma tabela chamada {[[0]}. Cada registro tem um ID único felizmente, e seu na coluna chamada ID
.
Como posso retirar isto e deixar uma entrada única (linha) dentro da tabela pf_main
para cada pessoa??
agradeço antecipadamente as vossas respostas...
5 answers
first
, last
, e dob
constitui uma "pessoa". Minha sugestão é construir um índice sobre a "pessoa" e então fazer a abordagem truncate
/re-inserir.
Na prática, isto parece:
create index idx_pf_main_first_last_dob on pf_main(first, last, dob);
select m.*
into temp_pf_main
from pf_main m
where not exists (select 1
from pf_main m2
where m2.first = m.first and m2.last = m.last and m2.dob = m.dob and
m2.id < m.id
);
truncate table pf_main;
insert into pf_main
select *
from temp_pf_main;
SELECT
ID, first, last, dob, address, city, state, zip, telephone,
ROW_NUMBER() OVER (PARTITION BY first, last, dob, address, city, state, zip, telephone ORDER BY ID) AS RecordInstance
FROM PF_main
Dar-lhe-á o "número" de cada item único (ordenado por Id)
Por isso, se tiver os seguintes registos:
Id, último, primeiro, D. N., endereço, cidade, estado, zip, telefone
006, trevelyan, alec, '1954-05-15', '85 Albert Embankment', 'London', "UK", "1SE1 7TP", 0064
007, bond, james, '1957-02-08', '85 Albert Embankment', 'London', "UK", "1SE1 7TP", 0074
008, bond, james, '1957-02-08', '85 Albert Embankment', 'London', "UK", " SE1 7TP", 0074
009, bond, james, '1957-02-08', '85 Albert Embankment', 'London', "UK", "SE1 7TP", 0074
Obterá os seguintes resultados (nota na última coluna)
Pode Apagar Registos com registo > 1:006, trevelyan, alec, '1954-05-15', '85 Albert Embankment', 'London', "UK", "1SE1 7TP', 0064, 1
007, bond, james, '1957-02-08', '85 Albert Embankment', 'London', "UK", "1SE1 7TP', 0074, 1
008, bond, james, '1957-02-08', '85 Albert Embankment', 'London', "UK", "SE1 7TP', 0074, 2
009, bond, james, '1957-02-08', '85 Albert Embankment', 'London', "UK", "SE1 7TP', 0074, 3
WITH Records AS
(
SELECT
ID, first, last, dob, address, city, state, zip, telephone,
ROW_NUMBER() OVER (PARTITION BY first, last, dob, address, city, state, zip, telephone ORDER BY ID) AS RecordInstance
FROM PF_main
)
DELETE FROM Records
WHERE RecordInstance > 1
Outras respostas certamente dar-lhe-ão ideias quanto à sintaxe.
Com 2 bilhões de linhas, suas preocupações podem envolver outras coisas além da sintaxe, então eu vou lhe dar uma resposta genérica que funciona em muitas bases de dados. Se você não puder dar ao luxo de fazer a remoção ou cópia "online" em uma sessão, ou estão com pouco espaço, então considere a seguinte abordagem incremental.
Apaga este grande pode demorar muito, muito tempo a completar, como em horas ou até mesmo dias, e também pode correr o risco de falhar antes conclusao. Em alguns casos, a abordagem que funcionou melhor, surpreendentemente, foi um procedimento rudimentar, de longa duração armazenado que tomou pequenos lotes e cometeu todos os poucos registros (poucos sendo um termo relativo aqui). Poucos podem ter 100 ou 1000 ou 10000 discos. Claro que não parece elegante, mas o ponto é que é "incremental" e um consumidor de baixo recurso.
A ideia é identificar uma chave de parcionamento através da qual você pode abordar intervalos de registos (para partição do seu conjunto de trabalho), ou faça uma consulta inicial para identificar as chaves duplicadas de outra tabela. Em seguida, iterar através dessas teclas um pequeno lote de cada vez, excluir, em seguida, commit, e repetir. Se o fizer ao vivo sem uma tabela temp, certifique-se de manter os intervalos pequenos, adicionando critérios apropriados para reduzir os conjuntos de resultados, e manter o cursor ou ordenar tamanhos de área pequenos.
-- Pseudocode
counter = 0;
for each row in dup table -- and if this takes long, break this into ranges
delete from primary_tab where id = @id
if counter++ > 1000 then
commit;
counter = 0;
end if
end loop
Este proc armazenado pode ser parado e reiniciado sem se preocupar com um rollback gigante, e também funcionará de forma fiável durante horas ou dias sem grande impacto na disponibilidade da base de dados. In Oracle this could be undo segments and sort area sizes as well as other things, but in MSSQL I am not an expert. Eventualmente, acabará. Enquanto isso, você não está amarrando a mesa-alvo com fechaduras ou grandes transações, e assim DML pode continuar na mesa. A ressalva é que, se o DML continuar nele, então você potencialmente terá que repetir o instantâneo para a mesa de ids dup para lidar com quaisquer dupes que surjam desde o instantâneo.
Advertência: Isto não defrag blocos livres/linhas ou coalesce espaço excluído como completamente a construção de uma nova tabela, mas permite que ele seja feito on-line e sem alocação de uma nova cópia. Por outro lado, se você tiver a liberdade de fazê-lo on-line e / ou uma janela de manutenção, e as linhas duplicadas são maiores do que 15-20% de seus dados, então você deve optar pela abordagem" Criar tabela como Selecione * do original menos duplicates", como na resposta de Gordon, a fim de comprimir o segmento de dados em um densamente utilizado, segmento contíguo, e obter um melhor desempenho de cache/IO a longo prazo. No entanto, raramente são duplicados mais de uma fração de uma porcentagem do espaço.
As razões para tal incluem:
Uma tabela demasiado grande para criar uma cópia temporária.Caso contrário, veja a resposta do Gordon Linoff.2 - Você não pode ou não quer deixar cair a tabela original para fazer a troca uma vez que o novo está pronto.
Não se arranja uma janela de manutenção para fazer um gigante. operacao.
Para os meus clientes, construí uma consulta como a acima que devolve linhas que representam provavelmente duplicados, utilizando o endereço e o apelido como critério de correspondência. Em seguida, eles olham a lista de prováveis e clicam em "Apagar" ou "mesclar" nas linhas que eles escolhem para ser um duplicado.
Isto pode não funcionar no seu projecto (com milhares de milhões de linhas), mas faz sentido num ambiente onde tanto duplicações como dados perdidos precisam de ser evitados. Um único operador humano pode melhorar a limpeza de milhares de linhas de dados em poucos minutos, e eles podem fazê-lo um pouco de cada vez ao longo de muitos sessao.
(eu faço a maior parte do meu código sql no SAS PROC SQL, mas eu acho que você vai ter a idéia.)
A minha solução usa um subcontingente... /* dedupe */
proc sql ;
create table &delta. as
select distinct b.*, sub.mxasof
from &bravo. b
join ( select distinct Loan_Number, max(asof) as mxasof format 6.0
from &bravo.
group by Loan_Number
) sub
on 1
and b.Loan_Number = sub.Loan_Number
and b.asof = sub.mxasof
where 1
order by b.Loan_Number, b.asof desc ;