Gostaria de encontrar a primeira "lacuna" em uma coluna de contador em uma tabela SQL. Por exemplo, se houver valores 1,2,4 e 5, gostaria de descobrir 3.
Claro que posso colocar os valores em ordem e analisá-los manualmente, mas gostaria de saber se haveria uma maneira de fazer isso em SQL.
Além disso, deve ser um SQL padrão, trabalhando com diferentes SGBDs.
sql
gaps-and-islands
Touko
fonte
fonte
LAG(id, 1, null)
função comOVER (ORDER BY id)
cláusula.Respostas:
Em
MySQL
ePostgreSQL
:Em
SQL Server
:Em
Oracle
:ANSI
(funciona em qualquer lugar, menos eficiente):Sistemas que suportam funções de janela deslizante:
fonte
URL
também, embora possa ser codificado por QR, eu acho.[1, 2, 11, 12]
, isso iria encontrar apenas3
. O que eu adoraria encontrar é 3-10 em vez disso - basicamente o início e o fim de cada lacuna. Eu entendo que posso ter que escrever meu próprio script python que aproveita SQL (no meu caso MySql), mas seria bom se SQL pudesse me aproximar do que eu quero (eu tenho uma tabela com 2 milhões de linhas que tem lacunas, então vou precisar dividi-lo em pedaços menores e executar algum SQL nele). Suponho que eu poderia executar uma consulta para encontrar o início de uma lacuna, depois outra para encontrar o final de uma lacuna, e eles "mesclaram classificação" as duas sequências.NULL
, não0
, se a mesa estiver vazia. Isso é verdade para todos os bancos de dados.Todas as suas respostas funcionam bem se você tiver um primeiro valor id = 1, caso contrário, essa lacuna não será detectada. Por exemplo, se os valores de id de sua tabela são 3,4,5, suas consultas retornarão 6.
Eu fiz algo assim
fonte
Não há realmente uma maneira SQL extremamente padrão de fazer isso, mas com alguma forma de cláusula limitadora você pode fazer
(MySQL, PostgreSQL)
ou
(Servidor SQL)
ou
(Oráculo)
fonte
A primeira coisa que me veio à cabeça. Não tenho certeza se é uma boa ideia seguir esse caminho, mas deve funcionar. Suponha que a tabela seja
t
e a coluna sejac
:Edit: Este pode ser um carrapato mais rápido (e mais curto!):
fonte
LEFT OUTER JOING t2
exigiria que você tivesse umat2
mesa, que é apenas um apelido.Isso funciona no SQL Server - não posso testá-lo em outros sistemas, mas parece padrão ...
Você também pode adicionar um ponto de partida para a cláusula where ...
Portanto, se você tivesse 2000, 2001, 2002 e 2005, onde 2003 e 2004 não existiam, ele retornaria 2003.
fonte
A seguinte solução:
Numera as linhas ordenadas sequencialmente na cláusula " with " e, em seguida, reutiliza o resultado duas vezes com uma junção interna no número da linha, mas deslocado em 1 para comparar a linha anterior com a linha posterior, procurando IDs com uma lacuna maior que 1. Mais do que solicitado, mas mais amplamente aplicável.
A consulta interna produz:
A consulta externa produz:
fonte
Associação interna a uma vista ou sequência que possui todos os valores possíveis.
Sem mesa? Faça uma mesa. Sempre mantenho uma mesa fictícia só para isso.
Então,
fonte
Para
PostgreSQL
Um exemplo que faz uso de consulta recursiva.
Isso pode ser útil se você quiser encontrar uma lacuna em um intervalo específico (funcionará mesmo se a tabela estiver vazia, enquanto os outros exemplos não)
fonte
Meu palpite:
fonte
Este é responsável por tudo o que foi mencionado até agora. Inclui 0 como ponto de partida, para o qual será padronizado se nenhum valor também existir. Eu também adicionei os locais apropriados para as outras partes de uma chave de vários valores. Isso só foi testado no SQL Server.
fonte
Eu escrevi uma maneira rápida de fazer isso. Não tenho certeza se isso é o mais eficiente, mas dá conta do recado. Observe que ele não informa a lacuna, mas informa o id antes e depois da lacuna (tenha em mente que a lacuna pode ter vários valores, por exemplo 1,2,4,7,11 etc)
Estou usando sqlite como exemplo
Se esta for a sua estrutura de tabela
e estas são suas linhas
A consulta é
https://gist.github.com/wkimeria/7787ffe84d1c54216f1b320996b17b7e
fonte
fonte
Aqui está uma solução SQL padrão que é executada em todos os servidores de banco de dados sem alterações:
Veja em ação para;
fonte
Funciona com tabelas vazias ou com valores negativos. Acabei de testar no SQL Server 2012
fonte
Se você usar o Firebird 3, isso é mais elegante e simples:
fonte
fonte
Descobri que a maioria das abordagens funciona muito, muito lentamente
Presumo que a sequência comece em `1`.mysql
. Aqui está minha solução paramysql < 8.0
. Testado em registros de 1 milhão com uma lacuna perto do final ~ 1 segundo para terminar. Não tenho certeza se ele se encaixa em outros tipos de SQL.fonte
Se o seu contador está começando em 1 e você deseja gerar o primeiro número da sequência (1) quando vazio, aqui está o trecho corrigido do código da primeira resposta válido para Oracle:
fonte
fonte
Se os números na coluna forem inteiros positivos (começando em 1), aqui está como resolvê-lo facilmente. (assumindo que ID é o nome da sua coluna)
fonte