Je voudrais trouver le premier "écart" dans une colonne de compteur dans une table SQL. Par exemple, s'il y a des valeurs 1, 2, 4 et 5, j'aimerais en savoir 3.
Je peux bien sûr mettre les valeurs dans l'ordre et les parcourir manuellement, mais j'aimerais savoir s'il y aurait un moyen de le faire en SQL.
De plus, cela devrait être du SQL assez standard, fonctionnant avec différents SGBD.
sql
gaps-and-islands
Touko
la source
la source
LAG(id, 1, null)
fonction avecOVER (ORDER BY id)
clause.Réponses:
Dans
MySQL
etPostgreSQL
:Dans
SQL Server
:Dans
Oracle
:ANSI
(fonctionne partout, moins efficace):Systèmes prenant en charge les fonctions de fenêtres coulissantes:
la source
URL
également, bien qu'elle puisse être codée QR, je pense.[1, 2, 11, 12]
, ce serait seulement trouver3
. Ce que j'aimerais qu'il trouve, c'est 3-10 à la place - essentiellement le début et la fin de chaque écart. Je comprends que je devrais peut-être écrire mon propre script python qui exploite SQL (dans mon cas MySql), mais ce serait bien si SQL pouvait me rapprocher de ce que je veux (j'ai une table avec 2 millions de lignes qui a des lacunes, je vais donc devoir le découper en petits morceaux et exécuter du SQL dessus). Je suppose que je pourrais exécuter une requête pour trouver le début d'un intervalle, puis une autre pour trouver la fin d'un intervalle, et les "fusionner le tri" des deux séquences.NULL
, non0
, si la table est vide. Cela est vrai pour toutes les bases de données.Vos réponses fonctionnent toutes bien si vous avez une première valeur id = 1, sinon cet écart ne sera pas détecté. Par exemple, si vos valeurs d'ID de table sont 3,4,5, vos requêtes renverront 6.
J'ai fait quelque chose comme ça
la source
Il n'y a pas vraiment de méthode SQL extrêmement standard pour ce faire, mais avec une forme de clause limitative, vous pouvez le faire
(MySQL, PostgreSQL)
ou
(Serveur SQL)
ou
(Oracle)
la source
La première chose qui m'est venue à l'esprit. Je ne sais pas si c'est une bonne idée d'aller dans cette direction, mais cela devrait fonctionner. Supposons que la table est
t
et que la colonne estc
:Edit: Celui-ci peut être un tick plus rapide (et plus court!):
la source
LEFT OUTER JOING t2
vous obligerait à avoirt2
table, qui est juste un alias.Cela fonctionne dans SQL Server - impossible de le tester sur d'autres systèmes mais cela semble standard ...
Vous pouvez également ajouter un point de départ à la clause where ...
Donc, si vous aviez 2000, 2001, 2002 et 2005 où 2003 et 2004 n'existaient pas, cela renverrait 2003.
la source
La solution suivante:
Numérote les lignes ordonnées de manière séquentielle dans la clause " with ", puis réutilise le résultat deux fois avec une jointure interne sur le numéro de ligne, mais décalée de 1 afin de comparer la ligne avant avec la ligne après, en recherchant les ID avec un écart supérieur à 1. Plus que demandé mais plus largement applicable.
La requête interne produit:
La requête externe produit:
la source
Jointure interne à une vue ou une séquence qui a toutes les valeurs possibles.
Pas de table? Faites une table. Je garde toujours une table factice juste pour ça.
Ensuite,
la source
Pour
PostgreSQL
Un exemple qui utilise une requête récursive.
Cela peut être utile si vous souhaitez trouver un espace dans une plage spécifique (cela fonctionnera même si la table est vide, contrairement aux autres exemples)
la source
Ma conjecture:
la source
Celui-ci explique tout ce qui a été mentionné jusqu'à présent. Il inclut 0 comme point de départ, auquel il sera par défaut si aucune valeur n'existe également. J'ai également ajouté les emplacements appropriés pour les autres parties d'une clé à valeurs multiples. Cela n'a été testé que sur SQL Server.
la source
J'ai écrit un moyen rapide de le faire. Pas sûr que ce soit le plus efficace, mais fait le travail. Notez qu'il ne vous indique pas l'écart, mais vous indique l'id avant et après l'écart (gardez à l'esprit que l'écart peut être plusieurs valeurs, par exemple 1,2,4,7,11, etc.)
J'utilise sqlite comme exemple
S'il s'agit de votre structure de table
et ce sont tes rangs
La requête est
https://gist.github.com/wkimeria/7787ffe84d1c54216f1b320996b17b7e
la source
la source
Voici une solution SQL standard qui s'exécute sur tous les serveurs de base de données sans changement:
Voir en action pour;
la source
Cela fonctionne également pour les tables vides ou avec des valeurs négatives. Juste testé dans SQL Server 2012
la source
Si vous utilisez Firebird 3, c'est le plus élégant et le plus simple:
la source
la source
J'ai trouvé que la plupart des approches fonctionnent très, très lentement
Je suppose que la séquence commence à partir de «1».mysql
. Voici ma solution pourmysql < 8.0
. Testé sur 1M d'enregistrements avec un écart près de la fin ~ 1sec pour terminer. Je ne sais pas si cela correspond à d'autres saveurs SQL.la source
Si votre compteur est à partir de 1 et que vous souhaitez générer le premier numéro de séquence (1) lorsqu'il est vide, voici le morceau de code corrigé de la première réponse valide pour Oracle:
la source
la source
Si les nombres de la colonne sont des entiers positifs (à partir de 1), voici comment le résoudre facilement. (en supposant que l'ID est le nom de votre colonne)
la source