Eu tenho uma tabela que potencialmente armazena centenas de milhares de números inteiros
desc id_key_table;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id_key | int(16) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
Em um programa, eu tenho um grande conjunto de números inteiros. Gostaria de ver quais desses números inteiros NÃO estão na coluna id_key acima.
Até agora, desenvolvi as seguintes abordagens:
1) Itere através de cada número inteiro e execute:
select count(*) count from id_key_table where id_key = :id_key
Quando count é 0, a id_key está ausente na tabela.
Parece uma maneira horrível e horrível de fazer isso.
2) Crie uma tabela temporária, insira cada um dos valores na tabela temporária e execute JOIN nas duas tabelas.
create temporary table id_key_table_temp (id_key int(16) primary key );
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
select temp.id_key
from id_key_table_temp temp left join id_key_table as main
on temp.id_key = main.id_key
where main.killID is null;
drop table id_key_table_temp;
Essa parece ser a melhor abordagem, no entanto, tenho certeza de que existe uma abordagem muito melhor na qual ainda não pensei. Eu preferiria não precisar criar uma tabela temporária e usar uma consulta para determinar quais números inteiros estão ausentes.
Existe uma consulta adequada para esse tipo de pesquisa?
(MySQL)
Respostas:
Sua segunda solução usando o LEFT JOIN é de longe a melhor abordagem. Eu não usaria uma tabela temporária, usaria uma tabela regular e a preencheria com novos valores sempre que você quisesse executar a consulta.
fonte
Parece que o "grande conjunto de números inteiros" ainda é consideravelmente menor que a tabela com "centenas de milhares de números inteiros". Com essa suposição e a menos que haja uma maneira no MySQL de usar uma matriz de seus números inteiros como uma tabela em sua instrução SQL, sua segunda opção é provavelmente a melhor. Ele deve fazer uma varredura completa da tabela temporária e do índice na tabela principal. O principal benefício é que ele só precisa varrer o índice que contém centenas de milhares de números inteiros uma vez e apenas enviar os resultados ao cliente. Sua consulta pode (mas não precisa ser) reescrita da seguinte maneira:
fonte
Em vez de uma tabela temporária e inserção com
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
, você pode construir uma subconsulta com todos os valores que você está tentando verificar:fonte
Como observado no meu comentário, isso provavelmente é mais adequado ao stackoverflow. No entanto, acho que essas duas soluções não são as melhores:
A solução 1 requer várias chamadas selecionadas, muito ineficientes
A solução 2 é melhor, mas não tenho certeza de que o custo de inserir tantos valores seja a melhor solução.
Uma possível solução 3 seria fazer uma consulta:
e programaticamente obtenha a diferença do seu conjunto inteiro e do conteúdo do banco de dados. Na pior das hipóteses, (como são muitos números inteiros). Essa rota deve ser melhor que a Solução 1. A solução 2 também pode retornar muitos números inteiros (se a tabela tiver muitos que não estão no seu conjunto de dados), portanto depende ™!
fonte
Abordei isso bastante no StackOverflow , mas gostaria de elaborar mais sobre o uso da tabela permanente temp (PermTemp). ( temperatura permanente, isso não é um oxímoro ?)
No StackOverflow , eu tinha o procedimento armazenado test.CreateSampleTable e test.GetMissingIntegers fazem uma tabela de amostra e, em seguida, criam uma tabela temporária dinâmica para preencher antes de fazer o grande JOIN para encontrar diferenças.
Desta vez, vamos criar a tabela de amostra junto com a tabela de tabela permanente.
Aqui está test.LoadSampleTables:
Depois de executar isso, aqui estão as tabelas e seu conteúdo:
Aqui estão os gatilhos da tabela PermTemp
Agora, vamos importar um novo lote de registros, tabela test.weekly_batch, algumas chaves usadas antes, outras chaves com a marca nova:
Vamos pegar test.weekly_batch e mesclar com segurança em test.id_key_table_keys e formar a tabela test.new_keys_to_load:
Aqui está o resultado:
A partir desse ponto, basta usar a tabela new_keys_to_load como a lista de novas chaves de marca que serão importadas. Como new_keys_to_load é menor que a tabela PermTemp, você sempre deve usar new_keys_to_load no lado esquerdo do LEFT JOIN.
fonte