Ich möchte die erste "Lücke" in einer Zählerspalte in einer SQL-Tabelle finden. Wenn es zum Beispiel die Werte 1,2,4 und 5 gibt, würde ich gerne 3 herausfinden.
Ich kann die Werte natürlich in Ordnung bringen und manuell durchgehen, aber ich würde gerne wissen, ob es eine Möglichkeit gibt, dies in SQL zu tun.
Darüber hinaus sollte es sich um Standard-SQL handeln, das mit verschiedenen DBMS arbeitet.
sql
gaps-and-islands
Touko
quelle
quelle
LAG(id, 1, null)
Funktion mitOVER (ORDER BY id)
Klausel verwenden.Antworten:
In
MySQL
undPostgreSQL
:In
SQL Server
:In
Oracle
:ANSI
(funktioniert überall, am wenigsten effizient):Systeme, die Schiebefensterfunktionen unterstützen:
quelle
URL
, obwohl sie meiner Meinung nach möglicherweise QR-codiert sind.[1, 2, 11, 12]
, dann würde das nur finden3
. Was ich gerne finden würde, ist stattdessen 3-10 - im Grunde der Anfang und das Ende jeder Lücke. Ich verstehe, dass ich möglicherweise mein eigenes Python-Skript schreiben muss, das SQL nutzt (in meinem Fall MySql), aber es wäre schön, wenn SQL mich näher an das bringen könnte, was ich will (ich habe eine Tabelle mit 2 Millionen Zeilen, die Lücken aufweist). Also muss ich es in kleinere Teile schneiden und etwas SQL darauf ausführen. Ich nehme an, ich könnte eine Abfrage ausführen, um den Anfang einer Lücke zu finden, und eine andere, um das Ende einer Lücke zu finden, und sie könnten die beiden Sequenzen "zusammenführen, sortieren".NULL
nicht0
, wenn die Tabelle leer ist. Dies gilt für alle Datenbanken.Ihre Antworten funktionieren alle einwandfrei, wenn Sie einen ersten Wert id = 1 haben. Andernfalls wird diese Lücke nicht erkannt. Wenn Ihre Tabellen-ID beispielsweise 3,4,5 beträgt, geben Ihre Abfragen 6 zurück.
Ich habe so etwas gemacht
quelle
Es gibt nicht wirklich eine extrem standardmäßige SQL-Methode, um dies zu tun, aber mit irgendeiner Form von Begrenzungsklausel können Sie dies tun
(MySQL, PostgreSQL)
oder
(SQL Server)
oder
(Orakel)
quelle
Das erste, was mir in den Sinn kam. Ich bin mir nicht sicher, ob es eine gute Idee ist, diesen Weg überhaupt zu gehen, sollte aber funktionieren. Angenommen, die Tabelle ist
t
und die Spalte istc
:Bearbeiten: Dies kann ein Tick schneller (und kürzer!) Sein:
quelle
LEFT OUTER JOING t2
müssten einent2
Tisch haben, der nur ein Alias ist.Dies funktioniert in SQL Server - kann nicht in anderen Systemen getestet werden, scheint aber Standard zu sein ...
Sie können der where-Klausel auch einen Ausgangspunkt hinzufügen ...
Wenn Sie also 2000, 2001, 2002 und 2005 hätten, wo 2003 und 2004 nicht existierten, würde es 2003 zurückgeben.
quelle
Die folgende Lösung:
Nummeriert die geordneten Zeilen nacheinander in der " with " -Klausel und verwendet das Ergebnis dann zweimal mit einem inneren Join für die Zeilennummer, jedoch versetzt um 1, um die vorherige Zeile mit der nachfolgenden Zeile zu vergleichen und nach IDs mit einer Lücke größer als zu suchen 1. Mehr als gewünscht, aber allgemeiner anwendbar.
Die innere Abfrage erzeugt:
Die äußere Abfrage erzeugt:
quelle
Innerer Join zu einer Ansicht oder Sequenz, die alle möglichen Werte enthält.
Kein Tisch? Mach einen Tisch. Ich habe immer einen Dummy-Tisch dafür.
Dann,
quelle
Zum
PostgreSQL
Ein Beispiel, das rekursive Abfragen verwendet.
Dies kann nützlich sein, wenn Sie eine Lücke in einem bestimmten Bereich suchen möchten (dies funktioniert auch, wenn die Tabelle leer ist, während die anderen Beispiele dies nicht tun).
quelle
Meine Vermutung:
quelle
Dieser erklärt alles, was bisher erwähnt wurde. Es enthält 0 als Ausgangspunkt, auf den standardmäßig gesetzt wird, wenn ebenfalls keine Werte vorhanden sind. Ich habe auch die entsprechenden Positionen für die anderen Teile eines mehrwertigen Schlüssels hinzugefügt. Dies wurde nur auf SQL Server getestet.
quelle
Ich habe einen schnellen Weg dazu geschrieben. Ich bin mir nicht sicher, ob dies am effizientesten ist, erledigt aber die Arbeit. Beachten Sie, dass es Ihnen nicht die Lücke, sondern die ID vor und nach der Lücke angibt (denken Sie daran, dass die Lücke mehrere Werte haben kann, z. B. 1,2,4,7,11 usw.).
Ich verwende SQLite als Beispiel
Wenn dies Ihre Tabellenstruktur ist
und das sind deine Zeilen
Die Abfrage ist
https://gist.github.com/wkimeria/7787ffe84d1c54216f1b320996b17b7e
quelle
quelle
Hier ist standardmäßig eine SQL-Lösung, die ohne Änderung auf allen Datenbankservern ausgeführt wird:
Siehe in Aktion für;
quelle
Es funktioniert auch für leere Tabellen oder mit negativen Werten. Gerade in SQL Server 2012 getestet
quelle
Wenn Sie Firebird 3 verwenden, ist dies am elegantesten und einfachsten:
quelle
quelle
Die meisten Ansätze laufen sehr, sehr langsam ab
Ich gehe davon aus, dass die Sequenz bei "1" beginnt.mysql
. Hier ist meine Lösung fürmysql < 8.0
. Getestet an 1M-Datensätzen mit einer Lücke gegen Ende ~ 1 Sekunde bis zum Ende. Ich bin mir nicht sicher, ob es zu anderen SQL-Varianten passt.quelle
Wenn Ihr Zähler bei 1 beginnt und Sie im leeren Zustand die erste Sequenznummer (1) generieren möchten, finden Sie hier den korrigierten Code aus der ersten Antwort, der für Oracle gültig ist:
quelle
quelle
Wenn die Zahlen in der Spalte positive ganze Zahlen sind (beginnend mit 1), können Sie dies auf einfache Weise lösen. (vorausgesetzt, ID ist Ihr Spaltenname)
quelle